exercism.io - leap-year

56 views
Skip to first unread message

Floyd Arguello

unread,
Jul 30, 2015, 4:07:20 PM7/30/15
to Lisp Flavoured Erlang
Trying out the LFE exercisms, and I'm stuck on the first one!

Here's where I'm at:

(defmodule leap
    (export (leap-year 1)))

(defun leap-year (year)
    (and (= (rem year 4) 0)
        (or (/= (rem year 100) 0)
            (= (rem year 400) 0))))



I feel like that should work, but I get this error during compile:

ffdtm:leap $ rebar compile
==> lfe (compile)
==> lutil (compile)
==> color (compile)
==> ltest (compile)
==> leap (compile)
src/leap.lfe:4: unbound function: #(= 2)
src/leap.lfe:4: unbound function: #(= 2)
Compiling src/leap.lfe failed:
ERROR: compile failed while processing ~/exercism.io/lfe/leap: rebar_abort








What is the unbound function on line 4? Is (year) expected to be a function, and not an argument?

Best,
Floyd

Floyd Arguello

unread,
Jul 30, 2015, 4:09:30 PM7/30/15
to Lisp Flavoured Erlang, floyd.a...@gmail.com
Changing = to == did the trick.

Mason Staugler

unread,
Jul 30, 2015, 4:12:10 PM7/30/15
to Lisp Flavoured Erlang, floyd.a...@gmail.com

Robert Virding

unread,
Jul 30, 2015, 4:12:42 PM7/30/15
to Lisp Flavoured Erlang, floyd.a...@gmail.com, floyd.a...@gmail.com
Yes, there is no =/2 function, that is what the "unbound function: #(= 2)" error tells us. As you have found it is called ==/2.

Robert

Robert Virding

unread,
Jul 30, 2015, 4:21:39 PM7/30/15
to lisp-flavo...@googlegroups.com
Yes, in pattern matching = is used to show aliases, basically that two patterns should match at the same time. It is most commonly used like (= (tuple a b c) t) where they match that the data is a tuple and you bind a, b and c to the elements and it binds t to the whole tuple.

Robert


On 30 July 2015 at 22:12, Mason Staugler <ma...@staugler.net> wrote:

--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.
To post to this group, send email to lisp-flavo...@googlegroups.com.
Visit this group at http://groups.google.com/group/lisp-flavoured-erlang.
For more options, visit https://groups.google.com/d/optout.

Floyd Arguello

unread,
Jul 31, 2015, 12:42:27 PM7/31/15
to Lisp Flavoured Erlang, rvir...@gmail.com
Thanks for the responses - really enjoying LFE and the community!

Floyd



On Thursday, July 30, 2015 at 3:21:39 PM UTC-5, Robert Virding wrote:
Yes, in pattern matching = is used to show aliases, basically that two patterns should match at the same time. It is most commonly used like (= (tuple a b c) t) where they match that the data is a tuple and you bind a, b and c to the elements and it binds t to the whole tuple.

Robert

On 30 July 2015 at 22:12, Mason Staugler <ma...@staugler.net> wrote:

--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-erlang+unsub...@googlegroups.com.
Message has been deleted

H Durer

unread,
Aug 4, 2015, 2:50:28 AM8/4/15
to lisp-flavo...@googlegroups.com
I'm a newbie myself, so beware this might not be right...


On Tue, Aug 4, 2015 at 1:50 AM, Eric Bailey <ifsixw...@gmail.com> wrote:
As an exercise, I've started implementing the various map functions from the CL HyperSpec and ran into a bit of a roadblock their variadic nature.

I know certain functions like the arithmetic operators and ++ are (seem?) variadic, so I'm wondering how I can write my own.

Have you looked at the source code and checked how those functions are implemented?

I assume one possibility at least is to define various functions with the same name but differing arity.

 

[...]
 
Related question: Given a defined function, is there a way to get its arity?

As in:
    (defun f (x y) (+ x y))

    (... f) ; <= 2

erlang:fun_info/1 seems to be your friend here.  It returns a property list with various pieces of info about the function.  So if you only want the arity, use
proplists:get_value(arity, erlang:fun_info(...)).
 


Eric

unread,
Aug 4, 2015, 3:37:42 AM8/4/15
to lisp-flavo...@googlegroups.com
Unfortunately the source doesn’t really speak to me..

Thanks for the fun info about fun_info!




--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.

Eric

unread,
Aug 4, 2015, 3:46:17 AM8/4/15
to lisp-flavo...@googlegroups.com
Looks like it can be done with macros:

(defmacro plus
  ((x) x)
  ((x y)
   `(+ ,x ,y))
  ((x y . zs)
   `(plus (plus ,x ,y) ,@zs)))

Is the “dot” syntax planned for deprecation? I vaguely remember hearing something about that..



On Aug 4, 2015, at 1:50 AM, H Durer <h.du...@gmail.com> wrote:

--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.

Duncan McGreggor

unread,
Aug 4, 2015, 7:50:17 PM8/4/15
to Lisp Flavoured Erlang
Yes, the canonical example for n-arity support in LFE is the macro hack. Robert gave it as an example in his FOSDEM talk (and slides). There's a version of it up on Rosetta Code, too:

It's not the dot syntax per se which is being deprecated, rather unquoted forms in patterns. You will need to use '(...) or (list ...) instead of (...) -- same for any other constructor/quoted forms valid in patterns. Your macro would need to be updated to:

(defmacro plus
  (`(,x) x)
  (`(,x ,y) `(+ ,x ,y))
  (`(,x ,y . ,zs)
   `(plus (plus ,x ,y) ,@zs)))

Note that all three patterns will need to be updated, since you were also using unquoted lists.

In general, you will probably find that an iterative approach will be faster (though when speed doesn't matter, the recursive functions in LFE can be quite beautiful). For instance, here's a fold over a sequence that clocks in at about 3 seconds:

> (set `#(,time ,result) (timer:tc (lambda () (lists:foldl #'+/2 0 (lists:seq 1 1000000)))))
#(2745963 500000500000)
> (* 1.0e-6 time)
2.7459629999999997

And then, defining a recursive add that's easy to use with long lists of integers, we see it take more than 4 times longer:

(defun plus
  (('() acc) acc)
  ((`(,head . ,tail) acc) (plus tail (+ head acc))))

> (set `#(,time ,result) (timer:tc (lambda () (plus (lists:seq 1 1000000) 0))))
#(11469620 500000500000)
> (* 1.0e-6 time)
11.469619999999999

However, I would just use (lists:sum ...) in this particular case:

> (set `#(,time ,result) (timer:tc (lambda () (lists:sum (lists:seq 1 1000000)))))
#(60255 500000500000)
> (* 1.0e-6 time)
0.060254999999999996

d


Eric Bailey

unread,
Aug 4, 2015, 8:20:56 PM8/4/15
to lisp-flavo...@googlegroups.com
I wish I could un-cross-post this. Sorry.

Thanks for the examples and the explanation. The quoting scheme makes perfect sense. I just couldn't think of it at the time.

I wholeheartedly agree that lists:sum is preferable. I was only trying to think of a trivial example to highlight my general question.

Thanks, Robert, for your explanation too. You seem to have gotten it on the right thread...

Robert Virding

unread,
Aug 4, 2015, 8:27:47 PM8/4/15
to Lisp Flavoured Erlang
Just to confirm what Duncan wrote. When you write a pattern you should write it in the same way as you would write to build the structure so you need to use cons, list or list*. So your macro would become:

(defmacro plus
  ((list x) x)
  ((list x y) `(+ ,x ,y))
  ((list* x y zs) `(plus (plus ,x ,y) ,@zs))
  ;((cons x (cons y zs)) `(plus (plus ,x ,y) ,@zs))          ;Without macros in the patterns
  )


Or to do as Duncan did and used the backquote macro in the patterns as well which expand to the same thing.

Robert

P.S. It is very strange, when viewing directly in google groups I see this message and the other comments to you original message in the exercism.io thread but in my mail I see them under variadic functions. Computers are strange.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-erlang+unsub...@googlegroups.com.
To post to this group, send email to lisp-flavoured-erlang@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Lisp Flavoured Erlang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-erlang+unsub...@googlegroups.com.
To post to this group, send email to lisp-flavoured-erlang@googlegroups.com.

Eric Bailey

unread,
Aug 4, 2015, 8:46:33 PM8/4/15
to lisp-flavo...@googlegroups.com


On Aug 4, 2015, at 7:27 PM, Robert Virding <rvir...@gmail.com> wrote:

Just to confirm what Duncan wrote. When you write a pattern you should write it in the same way as you would write to build the structure so you need to use cons, list or list*. So your macro would become:

(defmacro plus
  ((list x) x)
  ((list x y) `(+ ,x ,y))
  ((list* x y zs) `(plus (plus ,x ,y) ,@zs))
  ;((cons x (cons y zs)) `(plus (plus ,x ,y) ,@zs))          ;Without macros in the patterns
  )



Awesome! I didn't know about list*. Will definitely put that to good use at some point. For cases like these I prefer the back quoting, personally.


Or to do as Duncan did and used the backquote macro in the patterns as well which expand to the same thing.

Robert

P.S. It is very strange, when viewing directly in google groups I see this message and the other comments to you original message in the exercism.io thread but in my mail I see them under variadic functions. Computers are strange.

I made the mistake of replying to the exercism.io thread with my phone's mail client, deleting the context and naively assuming that a message to lisp-flavo...@googlegroups.com with a new subject would create a new thread in the group. I went back and deleted the reply and mirrored it in an actual new thread on my computer, but alas it was too late... Computers are strange, indeed.


To unsubscribe from this group and stop receiving emails from it, send an email to lisp-flavoured-e...@googlegroups.com.
To post to this group, send email to lisp-flavo...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages