• Kari
    61 replies, posted
[b]Intro:[/b] Kari is a programming language I'm currently working on. It's designed around the concept of currying - where functions only take one argument and return another function to take the next argument. Kari takes this concept even further and enforces that all functions must take one and exactly one argument. Kari has 7 data types: Function (subdivided into Kari Functions and Native Functions), String, Number, Boolean, Array, Object and Nil. [b]Getting Started:[/b] You can dive straight into Kari with the [url=http://trykari.charliesomerville.com]Try Kari online interpreter[/url]. You can also download the latest revision off GitHub at [url]http://github.com/charliesome/kari[/url] [b]Learn Kari:[/b] Kari's syntax is pretty simple. You assign values into variables like so: [code]123 => x [b]123[/b][/code] You call functions by typing the name of the function, followed by it's parameter, like so: [code]add 1 2 [b]3[/b][/code] You can play with arrays like so: [code] [1, 2, 3] => myarray [b][1,2,3][/b] each myarray (n -> mul n 2) [b][2,4,6][/b] where myarray (n -> gt n 1.5) [b][2,3][/b] ind myarray 1 [b]2[/b] len myarray [b]3[/b] [/code] Objects are somewhat similar: [code] { one = 1, two = 2, three = 3 } => myobj [b]{one=1,two=2,three=3}[/b] myobj.three [b]3[/b] lookup myobj "three" [b]3[/b] keys myobj [b]["one","two","three"][/b] keyexists myobj "four" [b]false[/b] [/code] You can easily define your own functions. In fact, there are no 'blocks' in Kari like in other languages. It's all functions! [code] (put "hello world") => hello_world [b](function)[/b] hello_world! [b][highlight]"hello world"[/highlight][/b] [b](nil)[/b] (n -> add 1 n) => increment [b](function)[/b] increment 5 [b]6[/b] if true ( put "yes!" ) [b][highlight]yes[/highlight][/b] [b](nil)[/b] for 1 5 (n -> put n) [b][highlight]1 2 3 4 5[/highlight] (nil)[/b] for 1 5 @put [b][highlight]1 2 3 4 5[/highlight] (nil)[/b] [/code] While loops are slightly more complex, since they take two functions - a condition and the 'block' function. The condition is evaluated every iteration and is expected to return a boolean. [code] 0 => i [b]0[/b] while (lt i 5) ( add i 1 => i put i ) [b][highlight]1 2 3 4 5[/highlight] (nil)[/b] [/code] That's as much as I can think of off the top of my head. I welcome anyone who's interested to give Kari a shot. Please post any questions and constructive criticism in this thread, and I'll try to make you happy :v: There's no proper site for Kari yet, and no definitive function or language reference. I'm working on this and there should be one soon. Thanks!
As much as I'd like to try Kari, its trykari implementation is flawed. Often, commands entered will time out - the sooner you fix this, the more likely people will try it out.
[QUOTE=Nipa;24976372]As much as I'd like to try Kari, its trykari implementation is flawed. Often, commands entered will time out - the sooner you fix this, the more likely people will try it out.[/QUOTE] If you're getting timeouts, just refresh. It likes to spit out a few timeouts after the web application has just started up (it stops itself after a period of inactivity, the next request starts it up again)
Kari is a bit absurd in my opinion. Doesn't make it less awsm, tho :D
Seems pretty cool.
This seems a rather odd language, in my opinion
So "if" is a function taking a condition which, when true, returns a function taking a function then running it, or when false, returns a function taking a function which does nothing? Or is "if" a specially handled keyword? If it is a function, how come the function passed in your example can take no arguments? I suspected "help!" was simply a function taking no arguments, so I defined a function "test!" like: [code] >> (put "test") => test! => (nil) >> test! test => (nil) [/code] Which brings me to my actual question - how do I pass the "test!" variable, which is a function taking no arguments, to a higher-order function? edit: Sorry if I'm being very confusing, Kari really needs its own set of terminology :v: Awesome project anyway :smile:
[QUOTE=jA_cOp;25052683]If it is a function, how come the function passed in your example can take no arguments? Which brings me to my actual question - how do I pass the "test!" variable, which is a function taking no arguments, to a higher-order function?[/QUOTE] [code] >> (put "test") => tes => (function) >> tes! test => (nil) >> for 1 3 @tes test test test => (nil)[/code] This is my first time using Kari, so I'm just guessing here :v: The actual function variable here is "tes", but you can call functions without passing any arguments by appending the !. With arguments you would just do [code]tes 1 2 "other argument"[/code] I'd also guess "if" is a function, not a keyword, as you can call it without arguments and it will throw a TypeException when it's missing the boolean argument. And you pass functions with @, as seen in my example above.
[QUOTE=raBBish;25052947][code] >> (put "test") => tes => (function) >> tes! test => (nil) >> for 1 3 @tes test test test => (nil)[/code] This is my first time using Kari, so I'm just guessing here :v: The actual function variable here is "tes", but you can call functions without passing any arguments by appending the !. With arguments you would just do [code]tes 1 2 "other argument"[/code] I'd also guess "if" is a function, not a keyword, as you can call it without arguments and it will throw a TypeException when it's missing the boolean argument. And you pass functions with @, as seen in my example above.[/QUOTE] Ah thanks, I missed the part about @ in the OP. I thought the ! was part of the actual identifier because it's allowed in variable assignment. Maybe that's a bug.
[QUOTE=jA_cOp;25053025]I thought the ! was part of the actual identifier because it's allowed in variable assignment. Maybe that's a bug.[/QUOTE] Kari's tokenizer is very forgiving. It replaces ! with a NilToken whenever the ! character is preceded by an identifier. [editline]12:01PM[/editline] [QUOTE=jA_cOp;25052683]So "if" is a function taking a condition which, when true, returns a function taking a function then running it, or when false, returns a function taking a function which does nothing?[/quote] That's correct. if is implemented like this: [cpp] public static Value @if(Value boolean) { boolean.AssertType<BooleanValue>(); return new NativeFunctionValue(fn => { fn.AssertType<BaseFunctionValue>(); if ((boolean as BooleanValue).Boolean) return (fn as BaseFunctionValue).Call(NilValue.Nil); return BooleanValue.False; }); } [/cpp] [url]http://github.com/charliesome/Kari/blob/master/kari/Lib/Control.cs#L33[/url] [quote] If it is a function, how come the function passed in your example can take no arguments? [/quote] If you're referring to this: [code]if true ( put "yes" )[/code] true is passed to if, which returns a new function which takes the ( put "yes" ) function. If you define a function without an argument, it still takes an argument, but it ignores this argument. [quote]Which brings me to my actual question - how do I pass the "test!" variable, which is a function taking no arguments, to a higher-order function?[/quote] As raBBish said, your 'test!' function is acually called test. You can pass a reference to it to another function by prefixing it with the @ sigil. [editline]12:04PM[/editline] [QUOTE=raBBish;25052947]I'd also guess "if" is a function, not a keyword, as you can call it without arguments and it will throw a TypeException when it's missing the boolean argument.[/QUOTE] That's correct, if you evaluate 'if' by itself, you can see that is it a native function. [code] >> if => (native-function) [/code]
Heh.. released this a few days ago and I would have been willing to try it in MineViewer. I was looking for a complete Lua port to C# (so it could be ran in mono) and found KopiLua.
[QUOTE=turb_;25053436]Kari's tokenizer is very forgiving. It replaces ! with a NilToken whenever the ! character is preceded by an identifier. [/QUOTE] Personally I'd much rather have a syntax error thrown at me than just silently letting it pass.
How do you return from functions? :saddowns:
It automatically returns the last value in a function.
[QUOTE=raBBish;25054460]How do you return from functions? :saddowns:[/QUOTE] You can use the <= operator to immediately return from a function, or it automatically returns the last evaluated value when it reaches the end [editline]01:20PM[/editline] [QUOTE=jA_cOp;25054150]Personally I'd much rather have a syntax error thrown at me than just silently letting it pass.[/QUOTE] You see the thing is, when values are encountered by the Kari Runtime, they're pushed onto the stack. [code]() => test![/code] That's perfectly valid code. It pushes (), assigns whatever's on top of the stack to test, then pushes nil.
[QUOTE=turb_;25055484] You see the thing is, when values are encountered by the Kari Runtime, they're pushed onto the stack. [code]() => test![/code] That's perfectly valid code. It pushes (), assigns whatever's on top of the stack to test, [highlight]then pushes nil.[/highlight][/QUOTE] But why is this behaviour useful? It sounds like an artifact of the implementation that wasn't implemented with a purpose. I'd regard that as a bug.
[QUOTE=jA_cOp;25055985]But why is this behaviour useful? It sounds like an artifact of the implementation that wasn't implemented with a purpose. I'd regard that as a bug.[/QUOTE] That's true. I'll make ! its own token which will only be valid after a function.
Have you thought any about error handling yet? Exceptions/continuations, maybe? Multiple return values?
Why did you choose to make it a sequence of functions?
[QUOTE=pkt;25081677]Why did you choose to make it a sequence of functions?[/QUOTE] It's simpler.
Any proof of Turing-completeness? :3: [editline]08:34AM[/editline] Write a Brainfuck interpreter in Kari, turb
Anyone tried to calculate the Fibonacci numbers? Last time I tried I failed miserably because it didn't have if else.
[QUOTE=Robber;25084428]Anyone tried to calculate the Fibonacci numbers? Last time I tried I failed miserably because it didn't have if else.[/QUOTE] I tried :v: [code](n -> put n if lt n 2 (n) if eq n 2 (add fib sub n 1 fib sub n 2) if gt n 2 (add fib sub n 1 fib sub n 2) ) => fib[/code] No idea if it works, it times out on the website and I'm too lazy to test with the real version.
Fixed some major issues in regard to out of order execution caused by a bug in the runtime. Turns out that I had made things way more complex than they needed to be ( [url]http://github.com/charliesome/Kari/commit/43b17b9552a13c177be54d16388f66df4cd26a3d#diff-3[/url] <-- look at all that red) Anyway, now closures work properly. [editline]07:27PM[/editline] [QUOTE=raBBish;25084484]it times out on the website[/QUOTE] No wonder it times out, I just tested it then and got a StackOverflowException :v:
Why are you doing stuff like this?: [cpp]var FunctionStack = new Stack<BaseFunctionValue>();[/cpp] What's the advantage of writing var FunctionStack over Stack<BaseFunctionValue> FunctionStack?
[QUOTE=Robber;25084428]Last time I tried I failed miserably because it didn't have if else.[/QUOTE] I implemented if_else for you :buddy: [img]http://ahb.me/x2H[/img]
Seems interesting, going to check it out more when I get home.
[QUOTE=turb_;25085139]I implemented if_else for you :buddy: [img]http://ahb.me/x2H[/img][/QUOTE] Thank you. :love:
[QUOTE=Darwin226;25085120]Why are you doing stuff like this?: [cpp]var FunctionStack = new Stack<BaseFunctionValue>();[/cpp] What's the advantage of writing var FunctionStack over Stack<BaseFunctionValue> FunctionStack?[/QUOTE] Nothing really, but why type out the full type name twice?
Are there no disadvantages? Is there any benefit from writing a full name?
Sorry, you need to Log In to post a reply to this thread.