find-all and match syntax

Started by cormullion, December 03, 2008, 03:52:03 PM

Previous topic - Next topic

cormullion

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


(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

#1
not:


(set 'fname  "ab")

but:


(set 'fname  'ab)

its a symbol not a string ;-)


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

DrDave

#2
Quote from: "Lutz"not:


(set 'fname  "ab")

but:


(set 'fname  'ab)

its a symbol not a string ;-)


> (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?
(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
(ab +)
And if you went back and made your letters into strings, then your first code works. That is
(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

#3
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:


(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:


Quotefind-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

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


(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):


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

cormullion

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