find-all and match syntax

Notices and updates
Locked
cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

find-all and match syntax

Post by cormullion »

I thought I asked this before, but I can't remember the answer (nor could I find it in the forum)...

Code: Select all

(set 't '(
 (aa 900) 
 (ac 908) 
 (ae 17) 
 (ad 21) 
 (ab 63) 
 (ab 65) 
 (ab 26) 
 (ab 25) 
 (ad 24) 
 (ab 24) 
 (ab 24) 
 (ab 24) 
 (ac 135)))

(println (find-all (list 'ab '+) t))
;-> ((ab 63) (ab 65) (ab 26) (ab 25) (ab 24) (ab 24) (ab 24))

(set 'fname  "ab")
(println (find-all  (list fname '+) t))
;-> ()
How do you use variables inside that 'match syntax' list?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

not:

Code: Select all

(set 'fname  "ab")
but:

Code: Select all

(set 'fname  'ab)
its a symbol not a string ;-)

Code: Select all

> (set 'fname  'ab)
ab
> (find-all  (list fname '+) t)
((ab 63) (ab 65) (ab 26) (ab 25) (ab 24) (ab 24) (ab 24))
> 

DrDave
Posts: 126
Joined: Wed May 21, 2008 2:47 pm

Post by DrDave »

Lutz wrote:not:

Code: Select all

(set 'fname  "ab")
but:

Code: Select all

(set 'fname  'ab)
its a symbol not a string ;-)

Code: Select all

> (set 'fname  'ab)
ab
> (find-all  (list fname '+) t)
((ab 63) (ab 65) (ab 26) (ab 25) (ab 24) (ab 24) (ab 24))
> 
While all of the above is true, some of us casual programmers get a better understanding if you show what went wrong during the evaluation. So, is this what happens?

Code: Select all

(set 'fname "ab")
("ab")
(list fname '+)
("ab" +)  ;<--- here is the real problem because even though find-all is passed a list, it doesn't find the matches you wanted because the list you passed isn't really what you thought it was? 

But the needed list is actually

Code: Select all

(ab +)
And if you went back and made your letters into strings, then your first code works. That is

Code: Select all

(set 't '(
 ("aa" 900)
 ("ac" 908)
 ("ae" 17)
)
etc.
...it is better to first strive for clarity and correctness and to make programs efficient only if really needed.
"Getting Started with Erlang" version 5.6.2

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Ah, thanks guys! I should have stopped writing code an hour earlier and gone to bed, and I was too tired to think clearly (enough)!

I think the problem is indeed with the confusion between strings and symbols. As the 'fname' suggested, it's a function (symbol), also treated like a string.

The problem is clarified like this:

Code: Select all

(set 't '(
  (sin 803) 
  (cos 811) 
  (sin 17) 
  (cos 28) 
  (sin 61)))

(set 'fname "cos")
(println " result " (find-all (list (sym fname) '+) t))

 result ((cos 811) (cos 28))  ; that works!

(set 't '(
  (Maths:sin 803) 
  (Maths:cos 811) 
  (Maths:sin 17) 
  (Maths:cos 28) 
  (Maths:sin 61) ))

(set 'fname "Math:cos")
(println " result " (find-all (list (sym fname) '+) t))

 result () ; that doesn't...? 
You can see why I was confused at midnight... I'm still confused... :)

One thing I noticed is that the manual often uses simple literal lists, without showing how expressions are introduced. For example:
find-all '(? 2) '((a 1) (b 2) (a 2) (c 4)))
is a useful indication of the function's behaviour, but doesn't show how to use existing symbols (and those quoted wild-card characters, which I learnt about first from this forum...).

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Hera are a couple solutions when the function name in string is part of a different namespace:

Code: Select all

(set 't '(
  (Maths:sin 803)
  (Maths:cos 811)
  (Maths:sin 17)
  (Maths:cos 28)
  (Maths:sin 61) ))

(set 'fname "cos")
(find-all (list (sym fname Maths) '+) t) 
=>((Maths:cos 811) (Maths:cos 28))


(set 'fname "'Maths:cos")
(find-all (list (eval-string fname) '+) t)
=> ((Maths:cos 811) (Maths:cos 28))

(set 'fname "Maths:cos")
(find-all (list (read-expr fname) '+) t)
=> ((Maths:cos 811) (Maths:cos 28))
The last solution avoids quoting the name inside the string, becuase 'read-expr' only translates it, but does not evaluate it.

But the best way is, too avoid the string in the first place (if you can):

Code: Select all

(set 'fname 'Maths:cos)
(find-all (list 'Maths:cos '+) t)

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

Thanks - the read-expr solution is the one for me...

Locked