Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

I am planning to write an improved GolfScript for even shorter programs that can do more things. This is not a challenge; it is a request for feedback and tips on what I should do. (see tags)

I'm not sure if this should be Community Wiki. If you think so, just flag for a moderator to convert it :)

This language will be very similar to GolfScript. It is still written in Ruby. However, it has a few differences:

  • Using ` as a string delimiter, because it's an uncommon character, so less escaping will be needed. (Another character can replace its function, like # (more on that later)). \` to escape a backtick, \\ to escape a backslash, and there are no other escape sequences. If you need a newline, just stick an actual literal newline in the string.
  • Using Ruby's Rationals for arbitrary precision floating point, one of GolfScript's major flaws.
  • The ability to convert types to other types. For example, you can convert a block to a string.
  • Regular expressions. Probably created with "...". Operators will be overloaded for them as well. For example, "\W"~{`Invalid: non-word character`}{`OK`}if. Will automatically execute when pushed from a variable, like blocks.
  • File and Date objects, to do more stuff that was impossible in GolfScript. These will not have literals, but will have functions for initializing them, such as `file.txt`fl (name of the file-making-function may change).
  • Hashes maybe, but I'm not sure on that one. Should I?
  • Helper functions to do even more. For example, `http://example.com`net for network access (again, net operator may be renamed). rb to execute a string as Ruby code. There will be many more of these; suggestions welcome.
  • No comments, so that # can be used for something else. If you want a comment, `comment here`; will work fine. (Maybe # can replace `'s function)
  • It will be completely rewritten in a way that it will be much easier to add functions. Basically, the code will be more readable. (Have you seen the GolfScript source? :/)
  • It will be on Github so it can be collaboratively worked on. I'll license it under MIT or something.
  • No final newline, so cheaty quines work :P

And I'm setting these apart because I think they're the most drastic and helpful changes (except maybe adding floating point):

  • It will have many Ruby functions built-in. For example, shuffle (which may be abbreviated to sf) (previously took 9 characters), tr (previously 14 chars), sample (sm, previously .,rand=), flatten (fl, previously ???), etc.
  • It will be mushed, like Rebmu. For example, now you can do ~:a0<{0a-}aIF (using a letter variable name) instead of ~:$0<{0$-}$if (overwriting the sort function). (example from here). Note that this way, it is case-insensitive, and numbers are not allowed in variable names. This is okay in my opinion since it's a golfing language :P
  • It will have debugging. I will add the ability to supply a flag specifying array delimiters, element delimiters, etc., number output (rational, float, or int?), stepping through instructions one at a time, tokenizing and outputting each token instead of running the program, etc.

So, my question is: what is there to improve? What do you think I should add?

Any other ideas for this, before I start coding it?

share|improve this question
1  
I'm not sure if this should be Community Wiki. If you think so, just flag for a moderator to convert it :) –  Doorknob Dec 31 '13 at 18:58
    
Do realize that if you add mushing you lose case sensitivity. –  marinus Dec 31 '13 at 19:03
    
@marinus I realize that. I should have made that clear; editing... –  Doorknob Dec 31 '13 at 19:04
    
Also what it really needs is a way to do explicit I/O (for interactive programs). The interpreter could check beforehand if the program uses explicit I/O, and only do implicit I/O if it doesn't. –  marinus Dec 31 '13 at 19:05
1  
@Claudiu My development on my new language is quite alive, although I've recently been fairly busy so I haven't done much with it for a little while. Some of these ideas are just not good ideas though, which I am not using :P –  Doorknob Mar 30 at 3:01
show 14 more comments

22 Answers

Flexible I/O

Golfscript cannot at present be used for interactive programs. I propose some functions for explicit input be added (i.e. readline, getchar and friends). The interpreter should see if the program uses these before running it.

If the program does not call any input functions, the interpreter should act like Golfscript normally does.

I wouldn't expect the interpreter to detect input functions in eval'ed code generated at runtime, but if it somehow can do that, kudos.

share|improve this answer
    
This is a great idea; limited io is one of golfscript's large limitations. +1 –  Doorknob Dec 31 '13 at 19:16
add comment

Shorter built-ins

Single-character aliases for all of the built-in commands which don't have them. I would use base a lot more if it were just B.

share|improve this answer
    
But what if you use b as a variable name? Still; good idea; you just remember to not use that name if you're going to use the function, and if you aren't using the function, then it doesn't affect you at all. –  Doorknob Dec 31 '13 at 19:24
    
@DoorknobofSnow, you can already use built-ins (and even tokens such as ^ or $) as variable names. It doesn't make that problem any worse. Besides, I suggested aliases to allow backwards compatibility, so you would just have to use the longer name if you'd assigned something else to the shorter alias. –  Peter Taylor Dec 31 '13 at 19:26
3  
Z for zip would also be very useful. –  Howard Dec 31 '13 at 19:29
    
Maybe we can release an official standard library for GolfScript. But I am unclear about how it can be included in solutions (missing #include and "#{IO.read'lib'}"~ is too long). –  Howard Jan 1 at 7:41
    
@Howard Now that's an idea... I could add libraries into my language, maybe like mylang -Llibname somefile.ext. –  Doorknob Jan 1 at 13:39
add comment

Numbers

Change the lexer such that leading 0 is not part of a number:

# current behaviour
01     # -> 1

# new
01     # -> 0 1

Also negative numbers should be written with _ instead:

# current behaviour
1 2-3   # -> -1 3

# new
1 2_3     # -> 1 2 -3
share|improve this answer
    
Wow, that's interesting. Usually you don't typically push two numbers in a row, but this would help with that a lot. The negative thing is great too, instead of 0 100- for negative 100. +1 –  Doorknob Dec 31 '13 at 19:30
    
I've thought about this before. There shouldn't be any support for negative integer literals at all. It's already handled by ~. E.g. -1 is 0~. This makes a small number of numbers longer by one char, but removes the moderately frequent need for whitespace after -. –  Peter Taylor Dec 31 '13 at 19:33
    
Wait a minute, how would you push, for example, 1001? I think you meant leading zero, not trailing. –  Doorknob Dec 31 '13 at 19:33
    
@DoorknobofSnow Right. –  Howard Dec 31 '13 at 19:39
    
What would you think about doing {0\-}:~; (~ negative-izes a number) and using not for bitwise (just like and or xor)? –  Doorknob Jan 1 at 1:22
show 2 more comments

Change the lexer

GolfScript's lexer treats a Ruby identifier (anything which matches the regex [_a-zA-Z][_a-zA-Z0-9]*) as a single token. If it instead treated [a-zA-Z]+ as a token that would free up _ to be a built-in and would allow an alpha variable to be followed by a literal integer without separating whitespace.

share|improve this answer
    
Well, currently I'm using simply [a-z]+|[A-Z]+, for the mushing, so underscore is free. This is an interesting and very unique idea though! +1 –  Doorknob Dec 31 '13 at 19:27
add comment

Array set operator

["A" "B" "C" "D" "E" "F"] -1 4 S    # -> ["A" "B" "C" "D" -1 "F"]

Any built-in we can make available for that?

share|improve this answer
    
+1 I started writing a blog post about implementing array set, but never finished it. It's currently extremely hard in full generality. This would make a big difference to some challenges. –  Peter Taylor Dec 31 '13 at 23:33
    
I can't believe this isn't built in to golfscript already. +1 –  Doorknob Jan 1 at 1:13
add comment

Combined div-mod

This is a bit more niche than some of the suggestions, but when working on number-theoretic programs I frequently find myself wanting an operation which pops two integers a and b from the stack and pushes a/b and a%b. (At present this is 1$1$/@@%).

share|improve this answer
    
Since it's so niche, maybe something like dvm for DiV-Mod. Thanks for all the ideas :-) +1 –  Doorknob Dec 31 '13 at 23:52
add comment

Access to the whole stack

GolfScript is a stack-based language, but access to all but the top three items on the stack is limited to <integer>$ to copy the nth item. It would be useful to have something like PostScript's roll command so that it's easier to work with more than three "live" variables.

Ideally there would be one-arg and two-arg versions, but if there aren't enough names around then the one-arg should get preference for a one-character one.

The one-arg one just takes the number of items to roll. E.g. 1 roll does nothing; 2 roll is equivalent to \; 3 roll is equivalent to @; 4 roll and for higher numbers doesn't have an existing equivalent; the closest that's possible is something like

]-4/()\+\+[]*-1%~

(and that doesn't even handle non-integers at certain positions on the stack, or active [, and almost certainly breaks inside loops too).

The two-arg one also takes an amount to roll; a b roll2 is equivalent to {a roll}b*.

share|improve this answer
    
So, like Ruby's rotate. You should edit this into the CW answer. –  Doorknob Dec 31 '13 at 23:54
    
@Doorknob, no. I'm talking about operating on a slice of the stack, not on an array. –  Peter Taylor Jan 1 at 8:41
    
Umm...I'm not sure what you mean. I'm not familiar with postscript, but roll just rotates the array, right? –  Doorknob Jan 1 at 13:37
    
@DoorknobofSnow, stack. An array is an item which goes on the stack. –  Peter Taylor Jan 1 at 14:10
    
Oh, so it rotates the whole stack. Ah, that might be useful! +1 –  Doorknob Jan 1 at 14:32
show 2 more comments

Unicode aliases

Multiple-character commands could have unicode aliases. This would save on the score when the score is counted in characters and not in bytes.

share|improve this answer
6  
uh... we don't want another APL... –  Jan Dvorak Dec 31 '13 at 19:40
1  
Golfscript isn't anything like APL, Unicode or no. We already have several other APLs, like J and K. (or even R which looks quite APL-inspired to me, to the point that you can do literal translations quite often) –  marinus Dec 31 '13 at 19:54
    
The distinguishing point about APL is that it uses a very different charset than anything else, not that it uses vector arithmetic natively. I like J, I use it, and I commonly upvote J answers. I've yet to upvote one APL answer. If I wanted to paint my programs instead of writing them, I'd use Piet. –  Jan Dvorak Dec 31 '13 at 19:57
    
I think APL is more legible than J, certainly more legible than Golfscript. –  marinus Dec 31 '13 at 20:06
add comment

% as builtin for product

[1 2][1 2 3]%  # -> [[[1 1][1 2][1 3]][[2 1][2 2][2 3]]]
share|improve this answer
    
+1; you could edit my CW answer and add this one –  Doorknob Dec 31 '13 at 22:45
add comment

Single-character identifiers

It's not like a code golf solution is going to have too many variables. And it would save on spaces.

share|improve this answer
    
Hmm.. This could also be done by changing the parser. Perhaps a flag to specify this behavior? Great idea! +1 –  Doorknob Jan 1 at 16:09
add comment

Stable sort

The $ builtin on blocks should perform a stable sort.

share|improve this answer
add comment

Make |, & and ^ built-ins do something useful on blocks

E.g. <array/string> <block> | can be used as index function

[0 -10 -20 30 40 -50 60] {0<} |   # -> [1 2 5]

Any ideas for <array/string> <block> & or <array/string> <block> ^?

share|improve this answer
    
What does array block = do now? –  Jan Dvorak Dec 31 '13 at 20:19
    
@JanDvorak Compare. Useful if you want to compare a string to a block, e.g. "0<" {0<} =. –  Howard Dec 31 '13 at 20:20
    
How often do you need that? I'd rather drop that, and use array block = for "select by predicate" –  Jan Dvorak Dec 31 '13 at 20:28
    
@JanDvorak select by predicate is already implemented using ,. –  Howard Dec 31 '13 at 20:29
    
oh, never mind. Go on :-) –  Jan Dvorak Dec 31 '13 at 20:29
show 1 more comment

Regex support

The lack of regex support has always struck me as odd in a language designed for golfing. It would be great to have

  • <string> <string> <string> y (aka tr, using Perl's one-char alias for it)
  • <string> <string> <string> s (substitute)
  • <string> <string> <block> s (substitute with callback)
  • <string> <string> m (match)
share|improve this answer
    
I already mentioned regex in my question. –  Doorknob Dec 31 '13 at 19:31
add comment

Builtins for current date/time

It is currently very quirky to get date/time using Ruby evals.

D     # -> [2013 12 31]
T     # -> [23 59 59]
share|improve this answer
    
Does that give date/time in Lima or Zulu? –  Peter Taylor Dec 31 '13 at 19:55
    
@PeterTaylor Don't know - times are changing ;-) –  Howard Dec 31 '13 at 19:56
    
@howard Did you mean, "The times, they are a-changing "? –  Jan Dvorak Dec 31 '13 at 19:59
    
Already mentioned as the Time type in the OP. –  Doorknob Dec 31 '13 at 22:47
add comment

A way to turn symbols back into code blocks

Currently, we can bind code blocks to symbols with :, but there's no way to reverse the process: executing a symbol bound to a code block just executes the block.

I can see a couple of ways to implement this:

  1. add new syntax, e.g. #foo to push the value of foo to the stack, even if it's a code block, or

  2. add an operator to expand every symbol in a code block, so that (using _ as the new operator), e.g. {2*}:dbl; {dbl dbl}_ would produce {2* 2*}.

I can see advantages to both methods. The latter could substitute for the former, at the cost of two extra chars ({foo}_ instead of #foo), but I can see some potential applications for the former syntax where those two chars would be prohibitive (e.g. using array #func % instead of array {func} %).

Meanwhile, the former syntax could be used to replace the latter if there was a convenient way to somehow iterate over the tokens in a code block (which could be useful on its own, anyway).


In either case, I'd propose that expanding symbols that are bound to native built-ins (i.e. implemented in Ruby code) should return some kind of stub that could be called to obtain the functionality of the built-in, while being either impossible or just unlikely to be overridden. For example #$ (or {$}_) could return e.g. {builtin_dollar}, where builtin_dollar would contain the actual implementation of the $ built-in (and #builtin_dollar or {builtin_dollar}_ should just return {builtin_dollar} itself).

This would allow built-ins to be redefined without losing access to their functionality (see my earlier suggestion), so that if I, say, for some reason wanted to swap the meanings of $ and @, I could just do #$ #@ :$; :@; (or {$}_ {@}_ :$; :@;).

share|improve this answer
    
One detail I'm not sure of is what the _ operator should do if the code block contains variable assignments. The obvious thing would be to just leave any :symbol tokens untouched and expand anything else, but this would cause _ to break any code using local variables. Making it not break such code might be impractically complicated, though. –  Ilmari Karonen Jan 1 at 18:00
1  
Your second version would fit together with an flatten operator on arrays: [[1] [2] [3]] _ -> [1 2 3]. –  Howard Jan 1 at 18:04
    
So what would be the result of 2:A;{1:A;A}_? –  Howard Jan 1 at 18:06
    
Naïvely, {1:A;2} (or, to be technical, {1:A builtin_semicolon 2} if the built-in expansion feature was included). If some kind of "local variable exclusion" feature was included, it might plausibly evaluate to just {1:A;A}. –  Ilmari Karonen Jan 1 at 18:09
    
Or to be even more technical {builtin_1 :A builtin_semicolon 2}. –  Howard Jan 1 at 18:17
show 7 more comments

Variable preset with command line args

Unfortunately, there isn't any char left unassigned, but maybe we can use A for that?

share|improve this answer
    
_ is available. Perhaps that? Anyway, yes, golfscript needs a way of taking cmd line args +1 –  Doorknob Dec 31 '13 at 22:45
add comment

Native Ruby functions that I should implement

This is Community Wiki; feel free to edit and add the functions you think I should implement!

Format: "nativeFunctionName (nameInMyLanguage)"

  • shuffle (sf)
  • tr (tr)
  • sample (sm)
share|improve this answer
add comment

Take features from APL and HQ9+ too!

  • Shortcuts, like in APL. EDIT: just saw the answer "unicode aliases". That's what I meant :)
  • Other golf-oriented shortcuts, like in H9+, HQ9+, CHIQRSX9+
share|improve this answer
    
Okay, so how would you propose that? Any specific ideas? –  Doorknob Dec 31 '13 at 19:17
    
unicode characters allowing to do complex things in just one character. –  xem Dec 31 '13 at 19:19
    
@Doorknob of Snow , I updated my answer with the shortcuts I'd like to see: those from APL, and those from CHIRQSX9+ :) –  xem Dec 31 '13 at 19:25
    
Hmm, the hq9+ thing seems too cheaty :-P –  Doorknob Dec 31 '13 at 19:25
    
It's golf oriented :P im my opinion your language should do at least as well :) –  xem Dec 31 '13 at 19:27
add comment

Clearly separating built-ins

e.g. capitals : built-ins ; making B for base feasable

share|improve this answer
1  
As mentioned above there is no need to separate. If someone likes to overwrite a builtin he should be able to do so. I even found useful applications of overwriting operators like {-}:+. –  Howard Dec 31 '13 at 20:18
    
No need, also this language will be case insensitive. –  Doorknob Dec 31 '13 at 22:47
2  
Since the goal is to provide less strokes per hole, having case sensitivity and more built-ins effectively leads towards the mission statement. –  Shingetsu Jan 1 at 3:50
add comment

Local variables / closures

One thing I really miss in GolfScript is the ability to temporarily change the value of a symbol.

In particular, there's currently no way to temporarily override the meaning of a "primitive" built-in: once you, say, redefine $, you're never going to sort anything in that program again. (Well, not without writing your own sort implementation, at least.) It would be really nice to be able to say, for example, that in this code block $ means something else, but still keep the normal meaning elsewhere.

Related to the above, it would be nice to bind symbols in a code block to their current value. Sure, I can write, say, {$-1%}:rsort and be able to use rsort to sort and reverse an array, but that works only as long as the definition of $ (or -1 or %) doesn't change, since my rsort function is still calling the global symbol $. It would be nice to be able to say "let rsort do what $-1% currently does, even if those symbols are later redefined."

In particular, the standard library could use this kind of binding. It's kind of surprising to realize that, say, changing n changes the behavior of puts, or that redefining ! completely messes up xor. (Then again, some caution should be exercised here, since, in particular, the ability to change the behavior of puts turns out to be turns out to be the only way to avoid printing a final newline in the current version of GS.)

Edit: Being able to turn symbols back into code blocks would go a long way towards implementing this functionality. In particular, the {foo}_ syntax suggested in that answer would effectively perform one level of static binding by expanding all symbols in a code block. Combine that with a fixpoint combinator for deep static binding, and Bob's your uncle...

share|improve this answer
    
Come on - all the fancy new languages celebrate lazy evaluation ;-) Let's keep that feature in GolfScript. –  Howard Jan 1 at 17:09
    
On second thought - you're right, it is more a feature of binding than evaluation. But then - static binding is more complex than it sounds - e.g. provide recursive calls inside a definition. –  Howard Jan 1 at 17:16
add comment

More built-in functions

Make all the single-letter variables a-z and A-Z perform some generic, useful function. Some built-ins that are lacking:

  • min and max: all or some of top 2 stack values, top n stack values, over an array
  • absolute value
  • sum and product of an array. why do {+}* when you can do S? You have 52 functions to work with here!
  • Manhattan distance (i.e. x1 y1 x2 y2 --> abs(x2-x1)+abs(y2-y1). Now it'd have to be @-A@@-A+ if A is a built-in absolute value. Granted this only came up caues of my most recent post but I always figured that'd be a good way to expand golfscript: write down what functions would be handy to have, collect them, and add them as built-ins.
  • Convert an integer to a one-character string (equivalent of python's chr).
  • Spill a string onto the stack (currently {}/)
  • A version of : that consumes what is stored. This would have to not get 'stuck' to identifiers to be useful.
  • Operators for >=, <=
  • As someone suggested, a way to put a variable containing a block onto the stack without executing it. So you could reduce ifs of the form 1{\}{|}if to something like 1?\?|if
  • Built-in base64 conversion and zlib support to make embedding data take less characters
  • Beyond base64, make a custom base93 encoding (using all printable characters that aren't the string delimiter).
  • Shortcuts for 1$, 2$, 3$, 4$, 5$
  • An operator to copy the top two stack items as they are, i.e. \.@.@\
share|improve this answer
add comment

It'd be nice if the value written or computed in the last line of a function was automatically returned

share|improve this answer
3  
It's stack-based, so... –  marinus Dec 31 '13 at 19:30
1  
There's no such thing as a function. –  Peter Taylor Dec 31 '13 at 19:31
    
Functions don't return anything... and they're called blocks –  Doorknob Dec 31 '13 at 19:32
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.