1

Following simple code to list files in a directory is from here:

(Directory name: '.')  
allFilesMatching: '*.st' 
do: [ :f | (f name) displayNl ]

However, it is not working and giving following error:

$ gst mysrc.st
Object: Directory error: did not understand #name:
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
Directory class(Object)>>doesNotUnderstand: #name: (SysExcept.st:1448)
UndefinedObject>>executeStatements (firstline.st:1)

I am working on GNU Smalltalk version 3.2.5 on Debian Stable Linux.

Where is the problem and how can it be solved?

tukan
  • 17,050
  • 1
  • 20
  • 48
rnso
  • 23,686
  • 25
  • 112
  • 234

1 Answers1

2

I don't know who has written it on the rosettacode, but the #name: selector is incorrect (does not exist in the Directory class). If you check the Directory class you won't find such selector there. Instead you will find a #working: selector. The selector has a description:

working: dirName
    Change the current working directory to dirName.

Your code will then look like this:

(Directory working: '.') allFilesMatching: '*.st' do: [ :f | 
   (f name) displayNl
]
tukan
  • 17,050
  • 1
  • 20
  • 48
  • Why do we need `(f name) displayNl`? I see that `f displayNl` also works. – rnso May 10 '19 at 08:29
  • 1
    You need to look at the stdout carefully to notice the difference. The `f displayNl` will work but it returns different output. The sending a message `#name` to `f` gives you whole the `name` (and path in this case) of the file (which is an instalce of a String). Sending only `displayNl` will give you the instance of a File (you will see the double quotes). You can try to do this in the block `[ :f | f isFile printNl ]` and `[ :f | f name isString printNl ]`. – tukan May 10 '19 at 08:37
  • @rnso do you understand the difference now? – tukan May 10 '19 at 09:42
  • Yes, very well explained. Why `(Directory working: '.')` should be in parentheses and not `allFilesMatching: '*.py'` ? Also `ff name` may not be in parentheses - it works both ways. – rnso May 10 '19 at 12:03
  • 1
    @rnso those are different issues. I'll address them step-by-step: **1.** is message `#allFilesMatching:do:` (`#allFilesMatching: aStringMask do: aBlock`) the whole is one message so you can't have #allFilesMatching: which would be different message. You are sending the message to the result of `Directory working: '.'` and not sending this message to `Directory`. **2**. The `ff name` is using them just for readability. It makes it easier for anyone reading the code to see that there is something done and then the result is printed. – tukan May 10 '19 at 12:25
  • 1
    Tukan, the documentation you pointed to in this answer seems to indicate that `Directory` is a subclass of `File`. If that is correct, then `Directory` should understand `#name:` as it is implemented in `File` (class side). – Leandro Caniglia May 10 '19 at 18:27
  • @LeandroCaniglia you are right, I'll have to check it tomorrow if the structure did change or what, why it does not work at the GNU Smalltalk I have tried, thank you for noticing it. – tukan May 10 '19 at 19:00
  • 1
    Also note that the semantics of `#working:` is different from the semantics of `#name:`. The former will change the current working directory while the latter will just create an instance of the desired folder. This is why `#name:` would have been better in this case. – Leandro Caniglia May 10 '19 at 19:12
  • @LeandroCaniglia apparently the link is really really old. Did not find the date on the page, but on other link, on the same page I found out that it is from 1991. In the most current documentation the superclass of Directory is an Object class, so the `#name:` is not available like it was before. – tukan May 11 '19 at 09:22