Interesting problem for me

Started by ale870, December 10, 2008, 12:44:03 AM

Previous topic - Next topic

ale870

#45
Lutz, is there any way  (generally speaking) to make a function that return a reference to an element of a list (like in the example before) instead returning a copy? Can I do that using contexts?
--

Lutz

#46
Not for user-defined functions without using contexts, but for built-in functions, indexed parts return the reference:


(set 'L (set 'L '(a b (c d e) f g))

(push 'Z (L 2)) => (Z c d e)

L => (a b (Z c d e) f g)


You can achieve similar in a user-defined function by packing the L in a namespace/context:


(define L:L '(a b (c d e) f g))

(define (my-push lst offset)
(push 'Z (lst offset)))

(my-push L 2) => (Z c d e)

L:L => (a b (Z c d e) f g)

ale870

#47
Your explanation is very clear, thank you Lutz!



just for information: in my blog I just started to write some workshops to "put all together" about my experience acquired in this topic (I want even to highlight the new things I learnt). Even if they are in italian language there is an "automatic" translator using google. I'm very happy if you read and correct/comment/etc... my workshops.

First workshop is at:



ORIGINAL (ITALIAN):

http://newlisp.wordpress.com/2008/12/15/convertitevi-workshop-1/">http://newlisp.wordpress.com/2008/12/15 ... orkshop-1/">http://newlisp.wordpress.com/2008/12/15/convertitevi-workshop-1/



TRANSLATION:

http://translate.google.com/translate?hl=it&ie=UTF8&sl=it&tl=en&u=http://newlisp.wordpress.com/2008/12/15/convertitevi-workshop-1/">http://translate.google.com/translate?h ... orkshop-1/">http://translate.google.com/translate?hl=it&ie=UTF8&sl=it&tl=en&u=http://newlisp.wordpress.com/2008/12/15/convertitevi-workshop-1/



Thank you!
--

itistoday

#48
I thought it'd be fun to implement this using streams...



Results:
> (print-stream (upper-other-case (stream-from-list '("a" "b" "c" "d" "e" "f" "g"))))
A b C d E f G "done"


The upper-other-case function which does this:
(define (upper-other-case s)
(join-streams
(every-other-stream (map-stream upper-case s))
(every-other-stream (tail s))
)
)


Other functions used by upper-other-case:
(define (join-streams s1 s2)
(if (empty-stream? s1)
s2
(empty-stream? s2)
s1
(letex (a (head s1)
b (tail s1)
c s2)
(cons-stream a (join-streams 'c 'b)))
)
)

(define (stream-from-list l)
(if (empty? l)
the-empty-stream
; underscore hack, newlisp namespace problem with:
; (stream-from-list '(a b c)) b/c of usage of vars a & b
(letex (_a (first l) _b (rest l))
(cons-stream '_a (stream-from-list '_b)))
)
)

(define (every-other-stream s)
(if (empty-stream? s)
the-empty-stream
(empty-stream? (tail s))
(letex (a (head s))
(cons-stream a (every-other-stream '())))
(letex (a (head s) b (tail (tail s)))
(cons-stream a (every-other-stream 'b)))
)
)


For the rest of the functions you can read: http://www.alh.net/newlisp/phpbb/viewtopic.php?p=11920">Streams in newLISP
Get your Objective newLISP groove on.

DrDave

#49
To pass the time while awaiting my turn at the medical center, I thought about how to take some of the information from this thread to produce a very fast method. Method9 was previously the fastest, so I included only method9 and my latest endeavor, method11; it smokes method9. I wanted to have a list large enough to give a run time of at least half a second. This required 16 iterations to construct source-list, resulting in length of 327680.



I think method11 still has code that is clear, easy to maintain, and efficient, assuming ending with an output list the same size as the source list is acceptable.


;; Generate the source list
;; To try out the really slow methods, reduce iterations to 2 or 3 and work your way up

(set 'source-list "a")  ;after generating source-list the first time, can comment out this line
(set 'iterations 16)  ; for new methods, use a small value like 3 to start

(if (< (length source-list) 4)
    (silent   ;;silent to supresses output of list generation. Use begin to see output
       (set 'source-list '("a" "b" "c" "d" "e"))
       (for (zz 1 iterations)  (push source-list source-list -1))
       (set 'source-list (flat source-list))
    )
)

(println (length source-list))

;; Need to reset these in case running the code several times in succession
(set 'newList nil 'results nil 'myeven? nil)

(define (method9 lst)
  (dolist (this-string lst)
    (if (odd? $idx)
        (push (upper-case this-string) newList -1)
        (push this-string newList -1)))
  newList)

(define (method11 lst)
   (while lst
     (set 'myeven? (not myeven?))
     (if (= myeven? true)
         (push (upper-case (first lst)) newList -1)
         (push (first lst) newList -1)
     )
     (pop lst)
   )
)

(push (list (time (method9 source-list)) "method9") results)
(push (list (time (method11 source-list)) "method11") results)

(println "======")
(map println (sort results))


Here are typical results on my system:  newLISP 10.0.0. WIN32, Windows XP pro



(531 "method11")

(3343 "method9")



EDIT-- and here is the version of odd? I used
(define (odd? num) (= (& num 1) 1))

Also, I actually prefer to use some intermediate functions rather than inlinng the code, like below. But there is quite a speed penalty to call the functions, if speed is the goal.


(define (process-even-members)
        (push (upper-case (first lst)) newList -1)
)

(define (process-odd-members)
        (push (first lst) newList -1)
)

(define (method11 lst)
  (while lst
   (set 'myeven? (not myeven?))
   (if (= myeven? true)
       (process-even-members)
       (process-odd-members)
   )
   (pop lst)
  )
)
...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

ale870

#50
Quote from: "DrDave"To pass the time while awaiting my turn at the medical center


O_O



No comment... :-)



(I have my best idea into the bathroom! Everyone has its own place to think, to ponder :-)



Great!
--

Lutz

#51
you could make it even shorter putting the 'pop' inside the 'if'


(while lst
     (if (setq myeven? (not myeven?))
         (push (upper-case (pop lst)) newList -1)
         (push (pop lst) newList -1)
     )

DrDave

#52
Quote from: "Lutz"you could make it even shorter putting the 'pop' inside the 'if'


(while lst
     (if (setq myeven? (not myeven?))
         (push (upper-case (pop lst)) newList -1)
         (push (pop lst) newList -1)
     )

Right, I considered that. But because no matter what happens in the 'if' block, there will be a 'pop', I decided to factor it out and write it just once.



Do you think it will make a speed difference?



Nevermind... I tested it. It DOES make it a bit faster to in-line the 'pop'. From a bit over half a second runtime to a bit under.
...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

Kazimir Majorinc

#53
Quote from: "ale870"Lutz, is there any way  (generally speaking) to make a function that return a reference to an element of a list (like in the example before) instead returning a copy? Can I do that using contexts?

Symbols can be used as references.



(set 'L (list 'L.0 'L.1 'L.2))



(set 'return-by-reference (lambda(lst i)(nth i lst)))

  (set (return-by-reference L 0) "i!")

  (set (return-by-reference L 1) "o!")

  (set (return-by-reference L 2) "let's go!")



(set 'dereference-list (lambda(lst)(map eval lst)))

  (println (dereference-list L))
;("i!" "o!" "let's go!")



It has its price, but I think it is The Way.
http://kazimirmajorinc.com/\">WWW site; http://kazimirmajorinc.blogspot.com\">blog.

ale870

#54
@Kazimir can you help me to understand what's happening here?!


(set 'L (list 'L.0 'L.1 'L.2))


What's happening in newLisp with that syntax?



And, generally, speaking, can you help me to understand your example? It seems really interesting and using advanced tricks, but I'm lost after the first row!!



What's happening there?



Thank you!
--

DrDave

#55
@Alesandro, you've been too long without alcohol in your system resulting in cloudy thinking LOL



It's all straight-forward, if you take it bit-by-bit.
(set 'L (list 'L.0 'L.1 'L.2))

This creates the list (L.0 L.1 L.2) and binds it to L.


(set 'return-by-reference (lambda(lst i)(nth i lst)))
This just defines a function. It is identical to writing this:
(define (return-by-reference lst i) (nth i lst))
This function has two paramters, a list and an integer used as an index. The function body finds the ith member in the list and returns it.


(set (return-by-reference L 0) "i!")
(set (return-by-reference L 1) "o!")
(set (return-by-reference L 2) "let's go!")

These three lines work the same. They simply set values to each member of the list L. It's a generic way to do  this on a list
(set 'L.0 "i!" 'L.1 "o!" 'L.2 "let's go!")

(set 'dereference-list (lambda(lst)(map eval lst)))
This is the same as (define (dereference-list lst) (map eval lst))
You can see that it take s a list as a paramter, then evaluates each member of the list.
(println (dereference-list L))
This is doing (eval L.0 )
(eval L.1)
(eval L.2)
...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

ale870

#56
Thank you, functional languages are still "a new thing" for me, even after many months and several bottles of alchol :-) !
--

DrDave

#57
Quote from: "ale870"Thank you, functional languages are still "a new thing" for me, even after many months and several bottles of alchol :-) !

It will make more sense the more you use it. I'm just a casual programmer, not a hard-core computer scientist like Kaz or Lutz or some of the others.



I'm not sure, but I think Kaz used 'return-by-reference' for his function name to emphasize that  a pointer is being used rather than returning a copy of the actual value.  Someone will verify or correct this, I'm sure.
...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

Lutz

#58
There is an easier, straight forward and safe way to pass and return data by reference to and from user-defined functions, when using default functors:


(set 'data:data '(a b c d e f))

(define (foo lst x)
(push x lst)
lst)

(foo data 99) => data

data:data => (99 a b c d e f)

; push one more than use the return value

(reverse (foo data 98)) => (f e d c b a 99 98)

data:data => (f e d c b a 99 98)


so basically when you call the function you pass the namespace handle only, which will pass it by reference and return it again. All list/array/string functions in newLISP now if they see a context they have to look for the list/array/string inside the default functor of the context which is <context>:<context>

newdep

#59
QuoteIt will make more sense the more you use it.


Personaly i have this problem ->

.. If you start studying it, its getting even more difficult ..

not because of its complexity but because of it flexibility.. ;-)
-- (define? (Cornflakes))