Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - nikus80

#1
newLISP newS /
December 08, 2006, 05:21:09 AM
yes.



yours:

> (get-index 6 '(a b (c d e) f a))

(0)



mine:



> (get-index 6 '(a b (c d e) f a))

(4)



I wanted get flat length to return 1 on atoms, so it's more like:

(define (get-flat-length lst)

    (if (list? lst) (length (flat lst)) 1))
#2
newLISP newS /
December 07, 2006, 10:33:58 AM
True, but get-index doesn't work with duplicated items.

Of course that didn't seem to be an issue, but that's why I went the hard way. I got it working now.


(define (get-index ind lst (current 0))
  (if (not (list? lst)) '()
    (let (len (get-flat-length (first lst)))
       (if (> ind (- len 1))
          (get-index (- ind len) (rest lst) (+ 1 current))
          (cons current (get-index ind (first lst)))))))

(define (get-flat-length lst)
  (cond
        ((null? lst) 0)
        ((list? lst) (+ (get-flat-length (first lst)) (get-flat-length (rest lst))))
        (true 1)))
         
(define-macro (flat-nth-set ind lst ele)
    (eval (append '(nth-set) (get-index ind (eval lst)) (list lst) (list ele))))


Sorry if any of you read the previous code, it was awful.

BTW I wasn't happy with the catch-dolist-throw pattern. Plain recursion seems shorter to me.
#3
newLISP newS /
December 05, 2006, 06:39:45 PM
Mmm, I think you CAN single index a list. If we make a function which given a flat index returns a list that can be used with nth-set, we can easily write a macro as

(define-macro (nth-flat-set)

    (eval (append '(nth-set) (get-index (args 0) (eval (args 1))) (rest (args))))))....



the function we need to write is get-index, which given something like



(get-index 3 '(a b (c d e)))

returns the list (2 1).



We can write it recursively, walking down a list. if we hit an element which is also a list, we calculate its length. if this list can hold the rest of the index, we cons the current index with get-index called on the rest of the index and this list.



I tried writing such a function, but it doesn't work. I need some help...

(define (get-index ind lst , current)
   (set 'current 0)
   (catch
    (dolist (e lst)
     (cond
      (= current ind)
        (throw (list current)
      (list? (car e))
      (let (len (get-flat-lenght (car e)))
       (if (> (- ind current) len)
        (set 'current (+ len current))
        (throw (cons current (get-index (- ind current) (car e))))))
      (set 'current (+ current 1)))))))


(define (get-flat-length lst)
  (length (flat lst)))


#4
newLISP newS / comma in parameter lists
December 02, 2006, 07:00:27 AM
I'm using newLISP v9.0 on win.

I read about comma in parameters lists but they don't seem to work, what I'm doing wrong?



(define (test2 , b c)

  ,)



(test2 1 2 3)

returns 1! the comma is bounded!. Why is that?
#5
newLISP newS /
December 02, 2006, 06:41:31 AM
I see what you mean.



(apply list '('a 'b 'c)) is equivalent to (list ''a ''b ''c)

so,

(apply qq '(a b c)) is equivalent to (qq 'a 'b 'c)



the thing is, I can't get rid of the quotes! with list, I can.



(apply list (list a b c)) is equivalent to (list a b c)

(apply qq (list a b c)) is not equivalent to (qq a b c)



In the first one, (list a b c) is evaled, then the resulting list is applied with list, without evaling its arguments since I've already evaled them. This works fine, since list is a function, and all it's arguments are evaled anyway. It works with any function btw.

Now, with apply qq, it isn't very straightforward. Cause (apply qq (list a b c)) is meant to work with functions only, that's what I meant early when I said applying a macro just felt weird. With apply, I can't get something that translates to (qq a b c). so the answer to "We haven't yet found, for my-or, a tail call idiom involving apply which works." is guess is: we won't.



The thing is, it does not matters. Just use fanda's idiom. Or better, make it a macro or something.



at first I thought:

(define-macro (fapply)

    (eval (cons (args 0) (eval (args 1)))))



but it doesn't works. I think is because



(define-macro (my-or)

    (let (v (eval (args 0)))

        (if v v (fapply my-or (rest (args))))))



when fapply evals (rest (args)), it thinks args refers to fapply args, not my-or args. I don't know which is the workaround to that. But for the moment, since there is no need to quote the first argument, just use:



(define (fapply)

    (eval (cons (args 0) (args 1))))



still, like I said, I'm not happy with applying macros unless it's inside another macro, which in that case I probably need fapply, not apply.
#6
newLISP newS /
December 01, 2006, 01:50:07 PM
Fanda, that's cool! that's exactly what I was wanting to do with apply!



for the rest, there is something I'm doing wrong? They don't work!
(define (prit)
(print "printed!"))
(define (ret-nil)
'())


(define-macro (my-or)
    (let (val (eval (args 0)))
       (if val val (apply my-or (rest (map eval (args)))))))

(define (my-or2 p)
    (if p p (if (args) (apply my-or2 (args)) p)))

(define-macro (my-or3)
  (if (empty? (args))
    nil
    (if (or (eval (args 0)) (= 1 (length (args))))
      (eval (args 0))
      (eval (cons 'my-or3 (rest (args)))))))

(define (fun-my-or2 )
(let (val (eval (args 0)))
(if val
val
(apply fun-my-or2 (rest (args))))))

(define-macro (my-or4 )
(apply fun-my-or2 (args)))

> (my-or nil (ret-nil) (cons 2 3) (prit))
printed!(2 3)
> (my-or2 nil (ret-nil) (cons 2 3) (prit))
printed!(2 3)
> (my-or3 nil (ret-nil) (cons 2 3) (prit))
(2 3)
> (my-or4 nil (ret-nil) (cons 2 3) (prit))
(2 3)
>


EDIT: (define (my-or p) (if p p (if (args) (apply my-or (args)) p)))  has the same problem
#7
newLISP newS /
December 01, 2006, 12:22:37 PM
it doesnt seems to work.

I need my-or to eval only the arguments needed. my-or as a function is not what I need.



(define (prit)

   (print "printed!"))

(define (ret-nil)

   '())



(define-macro (my-or)

(let (val (eval (args 0)))

(if val val (eval (apply my-or (rest (args)))))))



That doesn't work, because of the mystery quoting/appling problem.



try (my-or nil (ret-nil) (cons 2 3) (prit)), it returns '(). The my-or suggested by ricky returns '() too.



I think what you're receiving is the quoted list '(ret-nil), you eval it and it's still a non-null list, so it returns the list. then its evaled, and it returns the empty list. This is not desired.



About not knowing something is a macro or a function I can't understand why would I want macro and functions to behave identically, especially when I know macros don't have any speed execution advantage. When I use dolist, I know it's a macro. When I use my-or, I know it's a macro and I know it only evals what is needed and that it wont eval (prit).
#8
newLISP newS /
November 29, 2006, 06:47:28 PM
suppose newLisp had lexical scoping. Forget macros for a second.

imagine there is a function mydolist that receives a quoted code, and very much behaves like dolist


(set 'lst '(1 2 3))
(let (a 3)
    (mydolist '(e lst)
               '(+ a 3)))


when mydolist calls eval on '(+ a 3), what is the value of a? 3, you say. But only with dynamic scope. with lexical scope, if mydolist calls eval, it's evaled in the lexicals scope where mydolist was defined, which could be very different from the actual and where a could be undefined. So, with lexical scope, you have to receive a list and eval it in the current scope. Something like


(let (a 3)
   (eval (mydolist '(e lst) '(+ a 3))))

which, by the way, is exactly how common lisp macros work.

about appling macros, I thought about it and I could think of a place to use the technique. But it didn't worked.



(define-macro (my-or)

  (let (val (eval (args 0)))

    (if val val (apply my-or (rest (args))))))



this mimicks the recursive definition of (or) of scheme or common lisp.



This doesn't work because of the mystery quoting. If I call my-or with



(my-or nil (cons 2 3))

it returns the list (cons 2 3), not (2 3).



I think that, if applied. a macro should behave like a normal function. Usually, when you're appling a macro, you've already prevented it's argument from evaluation.



To my-or to work, you have to write it as a function, then make the macro a call to it.





(define (fun-my-or2 )

  (let (val (eval (args 0)))

   (if val

    val

    (apply fun-my-or2 (rest (args))))))



(define-macro (my-or2 )

  (apply fun-my-or2 (args)))



of course, i guess is no big deal. you could write a (define-recursive-macro) to do the hard work. But still, I think is not the desired behavior.
#9
newLISP newS /
November 28, 2006, 07:15:57 PM
No, what I meant to say is that newLisp-like macros are only useful with dynamic scope. They're useless with lexical scope since the code you receive often refers the current enviroment variables.
#10
newLISP newS /
November 28, 2006, 11:57:36 AM
I didn't mean you can't map or apply macro. What I meant to say is that if you are going to map 'n' apply your macro everywhere, it probably wants to be a function, not a macro.

if not, which would be a good example (I can't think of anything, but maybe I'm being too scheme/commonlispy



edit: BTW, when you're in the top level in common lisp, a macro also works dinamically. Macros work different in newLisp cause in common lisp you return a list of code which is then evaled in the place of the macro. In newlisp you don't need to do that because of dynamic scope, you don't return a list of code, you just execute it in place. Or am I wrong?
#11
newLISP newS /
November 28, 2006, 08:39:28 AM
I'm not very sure of what you're doing but macros arent supposed to be applied or mapped.

A macro doesn't evaluate his arguments, that means that, in newLISP, any call of a macro (mac a b c d) behaves like (mac 'a 'b 'c 'd) if mac were a normal function instead of a macro.
#12
newLISP newS /
November 27, 2006, 04:55:50 AM
If anything, you could write a macro to replace that or.



something like



(define-macro (nor)

(catch

(dolist (thisarg (args))

 (let (evalarg (eval thisarg))

 (if (or (isEmptyList? evalarg) evalarg)

   (throw evalarg))))....





or like



(define-macro (lor , evalarg)

(catch

(dolist (thisarg (args))

 (set 'evalarg (eval thisarg))

 (if evalarg

   (throw evalarg)))

  evalarg))....





I'm writing it directly, not very indented, but this is the idea. The first treats the empty list as true in the or. The second, if all elements fails, returns the last element which failed. oh and "isEmptyList?" is not the actual predicate (I don't know which it is)
#13
Anything else we might add? / Fun with builders!
November 22, 2006, 07:39:09 AM
maybe this should go on the wiki, but a negator could be useful too. given a function, it returns a function which applies not to the result. And for example there is no need to define (elem?) and (not-elem?). Also useful for mapping, filtering, etc.



sketch:
(define (negate fun)
  (letex (fun fun)
    (fn () (not (apply fun (args))))))


example:
> (map number? '(1 2 3 "hi"))
(true true true nil)
> (map (negate number?) '( 1 2 3 "lol"))
(nil nil nil true)


EXTRA EDIT:

I've been playing around and after trying a lil bit to make an loop/iter macro for newLISP, I came to a better idea, I hope you like it!



It's the collector idea. In common lisp



(loop for e in lst collect (+ e 1))



does exactly what it seems to. It conses a all the elements in the list plus one. Identic to



(map (fn (e) (+ e 1) lst)



The cool thing about the loop macro is that you can mix thing a lil bit. Instead of iterating over a list you could iterate numbers. And write



(loop for e from 1 to 10 collect (+ e 1))



To do that you would have to use a sequence and map, build a list and throw it away, like this:



(map (fn (e) (+ e 1) (sequence 1 10))



But this way you have to replicate in sequence everything you could do with a normal for. And not to mention that besides collecting you can append, sum, etc. and you can insert ifs and then do filtering, everything with loop only

Now, instead of a overly complicated loop macro, I present you to the simple newLisp collector!


(collector
(dolist (e lst)
  (if (and (number? e) (> e 1))
(build (+ 1 e)))))

It does what it looks likes. Every call to build is macroexpanded to a call to (set), accumulating a list and then returning it.



for example, if lst would have been (1 2 3 "a b" k 13)) it would have evaluated to (3 4 14).

The cool thing here is that unlike map, you can iterate over anything.


> [cmd]
 (collector
  (for (e 1 10)
  (if (> e 3)
(build (+ 1 e)))))
[/cmd]

(5 6 7 8 9 10 11)

Now, the real thing here is that you can easily make you own builders.

(custom-builder) is a function that receives the base case and a function that receives the building value and the total count symbol, and returns a list of code so you can make you own builders. And (builder) is a simple macro that allows to make simple builders on-the-fly, instead of of the more general (custom-builder), it receives a function with is to be applied to the total and current value and the total is set to the value returned. E.G.


> (builder * 1 (for (i 1 4) (build i)))
24




Maybe I'm reinventing the wheel, but it seems fun!





Oh, I almost forgot!


(define-macro (collector)
(let (collector-list '())
(eval
(cons 'begin
(expand (args)
  '((build
'(lambda (element)
(push element collector-list -1)))))))
collector-list))
(define (custom-builder)
   (expand
'(let (building basecase)
(eval
(cons 'begin
(expand (args)
'((build
(fn (element)
(build-function element 'building)))))))
building)
(list (list 'build-function (args 0)) (list 'basecase (args 1)))))
(define-macro (builder fun base)
(letex (fun fun base base)
(eval (custom-builder
(fn (num total) (set total (fun num (eval total))))
base))))


(btw, I think they're not very hygenic and I'm not sure how nested builder works, besides maybe a "builder collector" would be good if I want to build on the outer collector, but that would be very rare I think.)
#14
newLISP newS /
November 21, 2006, 05:16:07 PM
I just thought (rand 0) returned 0. Actually (rand 1) always returns 0, so it could be argued it is the true base case.

That code seems fine, but I wonder how good it is at shuffling. For example, when you insert a 2, it is much more likely that you'll end up with (1 2) than with (2 1), which kinda retracts from its randomness.

I actually wrote a permutation algorithm when trying to solve a logic exercise of SICP without using the amb evaluator (note: it's nothing like the amb evaluator of newLISP). It was kinda different, of course. I'm having a hard time trying to figure out how the (anagrams) procedure works, I guess I'm not used to that idiom (one idiom I find very easy to understand is the common lisp (loop) macro, I don't know why... it's very un-newLISPy, but I think it rocks :)
#15
newLISP newS /
November 21, 2006, 12:47:27 PM
wow, thanks for the quick response.

But I think that (rand 0) should always return 0, and to restart the counter one should have to write (rand 'restart) or something like that, 'cause it could be useful, I think... Just an opinion (of course, I can always write my own rand...).

Of course in this case the actual function should be:



(define (shuffle2 lst , acc)

(set 'acc '())

(dolist (e lst)

(push e acc (rand (+ 1 $idx))))

acc)



BTW, I guess that thing about the broken $idx explains why I was debugging it once and it worked anyway.