Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon.

Pages: 1-

Lisp challenge

Name: Anonymous 2014-09-13 7:11

Lisp macros can do anything, they say. But can they do typeclasses?
For the purpose of feasibility study, I'll simplify the challenge, of course. It will go like this:

Implement the form mappend such that

(mappend 2 3)

expands to

(+ 2 3)

and

(mappend "arst" "neio")

expands to

(concatenate 'string "arst" "neio")

(the above code is in Common Lisp, but you're free to use any Lisp and substitute the corresponding forms from that Lisp).

The expansion must happen no later than compile-time, with no runtime overhead.

Feel free to use Typed Racket, Shen, Arc, Clojure or any other Lisp.

Name: Anonymous 2014-09-13 8:17

Easily!
(defmacro mappend (a b)
(cond
((and (eql (infer-type a) 'integer) (eql (infer-type b) 'integer)) `(+ ,a ,b))
((and (eql (infer-type a) 'string) (eql (infer-type b) 'string)) `(concatenate 'string ,a ,b))
(t (error "syntax error"))))

Name: Anonymous 2014-09-13 8:49

The expansion must happen no later than compile-time, with no runtime overhead.

Haskell can't even do that. It's all about runtime overhead.

Name: Anonymous 2014-09-13 8:57

>>3
Haskell typeclass methods are usually dispatched at compile-time. Basically each instance is a dictionary of functions and once the compiler infers the type, it knows which dictionary to substitute the method from.

Name: Anonymous 2014-09-13 10:19

>>4
Most of Haskell is usually dispatched at compile time. But virtually none of it is guaranteed, and many things must happen at runtime. That's not a terrible thing, but the constraints of this challenge have nothing to do with implementing typeclasses, especially not with regards to Haskell.

Incidentally, I can do it in Io, which is a language that does nearly everything it can at runtime, yet it meets the criteria:

Io> Sequence setSlot("+", method(x, self .. x))
==> method(…)
Io> 1 + 1
==> 2
Io> "foo" + "bar"
==> foobar


There is no expansion, and no cost at all additional to that of calling + on Numbers originally. To get an additional expansion you'd have to call doString on something, or manually construct the call yourself. You can do the same thing in the same way in JS, Smalltalk, Self, CLOS and probably even Obj-C. It's not even dynamic dispatch, strictly speaking, it's just extremely late binding. (See: Alan Kay, Smalltalk + anything descendent from it.)

This isn't a typeclass in any meaningful way but, again, it meets the criteria (with the exception of being a mere descendent and not "a Lisp" proper.)

Name: Anonymous 2014-09-13 10:32

>>1
How are you meant to do it with no runtime overhead when it's a dynamically typed language? That makes no sense. I mean, sure, in dialects like Clojure you can use type hints which (I'm assuming) would cause it to be expanded at compile time, but that's dependent on the context in which the macro is being used.

Name: Anonymous 2014-09-13 11:10

>>6
Not all Lisps are "dynamically typed", thank goodness.

Name: Anonymous 2014-09-13 12:08

(define-syntax mappend
(λ (stx)
(syntax-case stx ()
((_ 2 3) #'(+ 2 3))
((_ a b) (let ((x (syntax->datum #'a))
(y (syntax->datum #'b)))
(and (string? x)
(string? y)
(string=? x "arst")
(string=? y "neio")))
#'(string-concatenate a b)))))


Your ill-defined challenges are the best argument against formal verification I have seen so far, Haskell-kun.

Wouldn't a “proper” (read: handles more than literals) implementation of this require type inference? After all, evaluating the arguments during compile-time defeats the intended purpose of makeshift type classes.

Name: Anonymous 2014-09-13 21:00

>>7
The ones that are actually get used for things are.

Name: Anonymous 2014-09-14 4:22

Jesus Christ.
Lisp has to be the ugliest language I've seen since Brainfuck.

Name: Anonymous 2014-09-14 4:25

>>10
I know you're trolling. It's very pretty in fact. Elegant looking and logical.

Name: Anonymous 2014-09-14 4:32

>>11
Yeah, you deluded yourself so far that you think >>8's code looks pretty or elegant.

Name: Anonymous 2014-09-14 4:48

>>12
Yeah, you're an autist with other mental issues as well and too stupid to go out and fulfil your dreams of quality computing and so you go on here and rant about how all languages suck and lisp is the worst because its the language that all the cool kids on here like.

Name: Anonymous 2014-09-14 6:20

>>13
I didn't say it was the worst. Just that it's pretty ugly.

Name: Anonymous 2014-09-14 7:00

>>14
your moms ugly faggot

Name: Anonymous 2014-09-15 3:42

>>2
The function COMMON-LISP-USER::INFER-TYPE is undefined.
[Condition of type UNDEFINED-FUNCTION]

Name: Anonymous 2014-09-15 4:46

>>8

evaluating the arguments during compile-time defeats the intended purpose of makeshift type classes.

In practice you'll have to explicitly supply type signature. I.e. invoke (mappend a b) as (mappend (the string a) (the string b))

That is why statically typed languages are always harder to learn and more involved than dynamically typed ones. Otherwise Java wouldn't have lost to JavaScript.

Name: Anonymous 2014-09-17 20:15

>>1
Let's one up your challenge and have it perform the calculation at compile-time. After all, in Lisp, if we know the types of expressions at compile-time, they're literal expressions.

(defmacro mappend (a b)
(cond
((stringp a)
(cond ((stringp b)
(concatenate 'string a b))
(t (error "Types do not match!"))))
((integerp a)
(cond ((integerp b)
(+ a b))
(t (error "Types do not match!"))))
(t (error "Unsupported type(s)."))))

CL-USER> (macroexpand '(mappend 2 2))
4
T
CL-USER> (macroexpand '(mappend "a" "B"))
"aB"
T
CL-USER>

Name: Anonymous 2014-09-17 22:36

An optimizing compiler could infer the type of the arguments to mappend at compile time and perform the dispatch at compile time.

(defmethod mappend ((x number) (y number))
(+ x y))

(defmethod mappend ((x string) (y string))
(concatenate 'string x y))

(print (mappend 2 3))
(print (mappend "2" "3"))

Name: Anonymous 2014-09-21 17:40

>>2
Bullshit, CL doesn't have "infer-type".

>>17
No you won't, provided your language has type-inference (which Java-shit doesn't, as well as Scala-shit and in fact any OOP-shit).

Name: Anonymous 2014-09-21 19:12

>>20
You could write one, though, sort of. You'd need to pass in a hook to the variable's location in the source code, rather than the symbol itself though. This would be a good library.

Name: Anonymous 2016-07-11 5:37

(stopping the dubsfaggot from dubsbumping)

Don't change these.
Name: Email:
Entire Thread Thread List