last day (2069 days later) » 

6:04 AM
Woot tinylisp room!
 
(q \o/)
 
(disp "\o/")
 
(q mind=blown)
Does that work?
 
Now it does.
 
(d tinylisp (q awesome))
3
I think ^ should be part of the room description :)
 
6:06 AM
(q (You can do multiple words if you wrap them in a list.))
 
Huh
 
Do room descriptions allow code formatting?
 
How would you go about defining a -> macro?
I can't figure out a way, probably because I don't know how tinylisp works.
It could be part of the standard library
 
You'd probably have to quote everything
You could do (q (function without an arg))
And you could c onto the end of it
 
Also, standard library upload when?
 
6:09 AM
And then use v to eval it
Boom easy
 
@Pavel ... When I stop replying to chat messages and go do it. ;P
I'm thinking of splitting the library out into multiple files, so you don't have to load the whole thing if you just want (e.g.) basic math functions. One possible caveat is (potentially) complicated dependency graphs. If you load modules B and C, both of which load A, you'll get a ton of "name already defined" errors. Maybe I can work up a solution to that. Later.
Get it up first, make it perfect later.
 
Just one (load s) is golf-friendlier tho
 
Yes, but you see I'm also thinking of having a separate golfing library that redefines everything with shorter names.
Question: in library code, do you think it's more readable to use () or to do (d nil ()) and use nil?
 
I would say nil
 
Sure, nil is more readable.
 
6:17 AM
K
 
Loading the standard library should (d nil ()) so you can use nil in your own nongolf code.
 
What about the builtins? Aliases like def, cons, eval useful?
(Or define?)
 
Oh yeah, definitely
Also proper math operators +*-/
 
What about a redefinition library?
It should be alright
 
One question though: why does d make everything final?
 
6:22 AM
in The Nineteenth Byte, 50 mins ago, by DLosc
That's to enforce its status as an almost completely pure functional language.
@Qwerp-Derp I'd have to implement my idea for making name collisions less problematic. Otherwise two libraries that both used the redef library would cause a gajillion errors if you loaded both of them.
 
Yeah, true.
@Pavel That's functional programming for you
Yes I made a reverse thing with proper tail recursion!
(d last
  (q (
    (list)
    (i (e () (t list)) (h list)
      (last (t list))))))

(d _rev
  (q (
    (orig new)
    (i (e () (t orig)) (c (h orig) new)
      (_rev (t orig) (c (h orig) new))))))

(d rev
  (q (
    (list)
    (_rev list ()))))
 
Protip: empty lists are falsey, so it's more idiomatic to do (i (t list) ...) than (i (e () (t list)) ...)
 
@DLosc That doesn't work for some reason on TIO
 
You'll have to switch the order of the true and false branches too.
 
Oh yeah
Nah, can't really be bothered, I like this as is
I kinda prefer the tail-recursion bit to be at the bottom if possible
 
6:28 AM
I'll add a nil? function to the library, then. It'd look nicer.
 
@DLosc Yay!
Isn't that basically a not, though?
 
No, because 0 is also falsey.
 
There should be a builtin to define something in the local scope, so helper functions aren't loaded.
 
So like let in Clojure?
 
Basicly
 
6:32 AM
Yeah. I don't think that can be written natively in tinylisp because of the way scope works, so it would have to be a new builtin. I'll consider it.
 
Nah, I think that the current situation as-is should be fine.
 
Which is better for a long form of d: def or define?
 
It's more of a quality-of-life thing for load then anything actually needed.
And def, imo
 
def
 
mos def def, then
I also need to test whether it's possible to alias i to if and still get proper tail recursion out of it.
 
6:38 AM
Why does this not work?
(h (h (q (q (1 2 3)))))
Oh
 
Should return q
 
No, it tries to take the head of q and fails because q is a symbol not a list.
Better to use head/tail or car/cdr in the standard library? I'm leaning toward the former, both because they match the short versions and because it's less of a learning curve for non-LISPers.
 
Guys I think I made ->>!!!
(d last
  (q (
    (list)
    (i (e () (t list)) (h list)
      (last (t list))))))

(d _rev
  (q (
    (orig new)
    (i (e () (t orig)) (c (h orig) new)
      (_rev (t orig) (c (h orig) new))))))

(d rev
  (q (
    (list)
    (_rev list ()))))

(d append
  (q (
    (val list)
    (rev (c val (rev list))))))

(d ->>
  (q (
    (list)
    (i (e () (t list)) (v (h list))
      (->> (c (v (append (h list) (h (t list)))) (t (t list))))))))

(->>
  (q (
    5
    (s 0)
    (s 1)))
It works! Yes!
@DLosc Are you proud of me
 
(Pls add to standard library)
 
@Qwerp-Derp Haven't tried it out yet, but yes! That's pretty cool, and something I wouldn't have thought of.
 
6:48 AM
It's got a bunch of other useful functions in it
 
@Pavel I'll definitely trawl through this chat history and add stuff. Once the library's up on GitHub, y'all can also do pull requests I believe.
One more style question: I've defined a function called list. That means it's problematic to use list for parameter names. I understand the usual Lisp practice is to use lyst, which I've done, but it looks corny and might be confusing. Any suggestions for something better?
 
lst?
 
List?
 
Or to be even more succinct, ls?
 
I think I like ls
 
7:03 AM
Hm. It's between ls and List for me. I'm not altogether satisfied with ls, but it is better than lst (which I tend to read as last) and lt (which I tend to read as "less than"). List could be confusing because the only difference is capitalization. On the other hand, if we made a convention of initial-caps parameter names, that might be a good thing.
 
@DLosc I don't really agree with that convention
 
It would be unusual, for sure.
 
The language Zilch actually requires that
Compiler errors otherwise
 
Should ; delimit comments?
Like regular lisp-like langs?
 
@Qwerp-Derp I have done it in a few golf submissions because I was using single-char parameter names and wanted to use L or S or some other letter that was already assigned to a built-in.
 
7:07 AM
I should start golfing in tinylisp
 
@Qwerp-Derp (def comment (macro words nil)) ;) But that only really works in the REPL, so I guess it would be good to add real comment syntax.
room topic changed to tinylisp: Discussion of the tinylisp programming language. (d tinylisp (q awesome)) (no tags)
 
:( it doesn't work
Maybe make it into a tag?
 
room topic changed to tinylisp: Discussion of the tinylisp programming language. (d tinylisp (q awesome)) (no tags)
 
@DLosc Why doesn't that work in regular TL?
 
room topic changed to tinylisp: Discussion of the tinylisp programming language. (d tinylisp (q awesome)) [(d] [(q] [awesome))] [tinylisp]
 
7:13 AM
The order is wrong
 
:( It doesn't work
@Pavel I think it's in alphabetical order
 
room topic changed to tinylisp: Discussion of the tinylisp programming language. (d tinylisp (q awesome)) (no tags)
 
Close enough
 
room topic changed to tinylisp: Discussion of the tinylisp programming language. (no tags)
 
OK that works
 
7:15 AM
@Pavel It does, but it's not too useful as comment syntax. You have to put it at top level; if you put it inside a function, you'll have an extra nil floating around somewhere, and if you put it inside a quoted list, you'll get the entire comment in there too.
 
Why not put it top level?
 
Sure, it works. It's just less useful. With real comment syntax you could annotate every line in a function if it would be helpful.
@Qwerp-Derp I've gotta thank you: I put (d tinylisp (q awesome)) in the library... loading it up for the first time and doing this:
tl> tinylisp
awesome
... was really satisfying.
 
@DLosc Yay!
 
Now to do some stress-testing before I commit.
Ha, found my first bug already :P
 
Really? I need to try it then.
 
7:29 AM
It was just a silly typo. Changed the name in a parameter list and forgot to change it in the function body.
 
@DLosc That does feel really satisfying
 
7:43 AM
Yeah, I don't think it's possible to alias i to if without breaking tail recursion, at least without some modifications to the interpreter. No big deal, it's only one character of readability.
 
Yeah that should be fine
@DLosc OK this doesn't work:
(d succ
  (q (
    (n)
    (->>
      (q (
        n
        (s 0)
        (s 1)))))))
I can't use ->> in an actual function
 
7:58 AM
Hm. What's the error message?
 
Error: referencing undefined name n
Error: cannot subtract non-integers
Error: cannot subtract non-integers
 
Huh. What's the output of just the ->> call?
 
So just on its own?
Like without the context of the function?
 
Right.
 
(->>
  (q (
    10
    (s 0)
    (s 1))))
Returns 11 as expected
 
8:07 AM
Oh, yes, I see the problem. You're quoting the whole argument to ->>. When you pass n instead of 10, the n doesn't get evaluated.
 
Ah
So what do I do?
 
I'm not sure the problem will be solved by wrapping (h list) in (v ...) in your definition, because the recursion would probably eval it too many times (not a problem if it's a number, big problem if it's a list). Maybe a helper function is in order... my brain is elsewhere right now, but I know I ran into similar stuff when writing some of my library functions, so maybe you can look to those for inspiration once I commit them (shortly).
I know metafunctions like that can get very confusing with quoting and eval'ing stuff.
 
 
1 hour later…
9:18 AM
Standard library is on GitHub! Once Dennis pulls it, it will be on TIO as well.
I also added a couple of builtins: a adds two numbers (because (s num1 (s 0 num2)) was getting really tedious), and type returns one of Int, Name, List, or Builtin based on the type of its argument.
 
Oh, cool
I improved the ->> thing!
(->> 10
  (s 0)
  (s 1))
But it still doesn't work inside functions, though, this time it enters an infinite loop I think
(d ->>
  (q (
    ()
    args
    (i (e () (t args)) (v (h args))
      (v (c (q ->>) (c (v (append (h args) (h (t args)))) (t (t args)))))))))
 
Keep at it! It'll be great when it works (as I have every confidence that it can, eventually).
Also, I only realized tonight that the version on GitHub (and therefore TIO) was still sending error messages to stdout. New commit sends them to stderr instead--big improvement.
 
Oh, cool!
The assignments are also getting sent to STDOUT as well - is there a way you can remove that?
 
Yeah, I was just typing up something about that vis-a-vis libraries.
Thing is, it can be useful sometimes.
 
If I do this:
(d succ
  (q (
    (n)
    (->> n
      (s 0)
      (s 1)))))
And call (succ 10), it enters an infinite loop...
At least, it times out on TIO.
Oh hey @Gareth!
 
9:30 AM
@DLosc So I dunno... maybe only in REPL mode, or make a command-line flag to toggle it? I'll think about that another time.
 
9:49 AM
OK this is weird...
(->> (q (1 2 3 4))
  (rev)
  (c 5))
This doesn't work for some reason
 
I've been hand-debugging the one where you call it with n. I think I've got this much:
args gets (n (s 0) (s 1)) (unevaluated, because it's a macro)
(h args) is n (again, unevaluated)
(h (t args)) is (s 0)
So (append (h args) (h (t args))) is (s 0 n)
 
Yup
 
When you try to evaluate this, it doesn't work because n is not defined in this scope. --Ah, I haven't mentioned the scope rules, have I?
Yeah. That is a bit of a problem.
 
Well crap
I don't think I can do this the way I intended then
 
So the only names that are in scope at any given point are 1) the parameters of the current function and 2) globals. There isn't any scope nesting, essentially.
So even if n is in scope in an outer call like succ, it won't evaluate as such inside the nested call to ->>.
 
9:58 AM
Well that sucks
 
What you can do is make ->> a higher-order function like this:
(->>
  (rev)
  (c 5))

returns

(q (
  (arg)
  (c 5 (rev arg))))
and then use it like this:
(d succ
  (q (
    (n)
    ((->>
       (s 0)
       (s 1))
     n))))
Not quite the same, but sort of the same functionality.
 
I could try it out
So it returns an actual quoted "string"?
 
No, there aren't any strings in tinylisp... what are you referring to exactly?
 
Like something that isn't eval'd
 
That's all that quote means: "don't eval this"
 
10:02 AM
Yeah
 
I should sleep. It's been fun. Keep me apprised of your progress!
 
10:23 AM
I've made it!
@DLosc I did the ->> thing you suggested!
(d _->>
  (q (
    ()
    args
    (i (e () (t args)) (c (q (arg)) (c (h args) ()))
      (v (c (q _->>) (c (append (h args) (h (t args))) (t (t args)))))))))

(d ->>
  (q (
    ()
    args
    (v (c (q _->>) (c (append (q arg) (h args)) (t args)))))))

(d succ
  (q (
    (n)
    ((->>
       (s 0)
       (s 1)) n))))

((->>
   (rev)
   (c (succ 4))
   (rev)
   (append 6)) (q (1 2 3 4)))
And best of all, it works!
 
 
1 hour later…
11:28 AM
@DLosc Is it possible to make a function that differentiates the first arg from the rest?
 
 
9 hours later…
7:59 PM
@Qwerp-Derp Cool! I'll have to try it once TIO function is un-borked.
(I tried to fix load on TIO and broke the whole thing. Fix pending.)
@Qwerp-Derp No, you have to use variadic args and do (h args) / (t args).
 
 
1 hour later…
9:53 PM
@DLosc Awesome! Does TL have tail call optimization?
 
10:15 PM
@Pavel Sure does! Try (1to 10000) for example (the max recursion depth is much less than 10000). It works for mutually recursive functions too: whenever the function body returns the result of calling another user-defined function, possibly inside some i conditions.
 
I've written a function to check primality
(def prime_
	(lambda
		(arg1 arg2)
		(i (equal? (mod arg1 arg2) 0)
			0
			(i (equal? arg2 2)
				1
				(prime_ arg1 (- arg2 1))))))
(def prime?
	(lambda
		(num)
		(i (equal? num 1)
			0
			(i (equal? num 0)
				0
				(prime_
					(i (less? num 0)
						(neg num)
						num)
					(-
						(i (less? num 0)
							(neg num)
							num)
						1))))))
I'm not sure if it works yet though
 
@Qwerp-Derp Looks good!
 
@DLosc it borks, I'm not sure why yet, can you look at it? You might spot it before I do.
 
First off, don't bother with disp, just do (prime? 5) to display the result. Second, you need (load library) at the top.
With the load, it almost works, but fails on 2.
 
Welp, forgot to load. Derp.
I think I'll special case 2 then
 
10:30 PM
You shouldn't have to if you've got the right algorithm, but I haven't looked at it that closely yet.
 
It's checking if (equal? (mod num (- num 1)) 0), and stops at 2. However, because the algorithm is written like a do-while rather than a while, it will always make that check at least once (except for 0 and 1 which have special cases), and bork.
 
Wait, (mod num (- num 1))?
 
Sort-of
Technically it's (mod arg1 arg2) in the helper function.
Where arg2 starts at (- num 1) and is decremented in a loop
 
Oh, I see.
Okay, so just swap your conditionals around to test (i (equal? arg2 1) at the outer level. That will make it a while instead of do-while type loop, right?
Here's my stab at it (doesn't handle negative numbers, tho--I think the usual definition is that -1 is prime and all other negatives aren't?)
 
10:53 PM
I don't know what the usual definition for negative numbers is, but I have to go right now, sorry.
 
11:28 PM
@DLosc Can you merge pull-request pls?
Is anyone on?
Should we make a "Tips for golfing in tinylisp" thing?
 
11:51 PM
@DLosc?
 
@Qwerp-Derp Yes, it will get the word out.
 

  last day (2069 days later) »