Pika Showdown:
# Just prints "Hello World!"
print("Hello World!")
> pika hello-world
Hello World!
> pika help hello-world
Just prints "Hello World!"
# Greets the Master
person |
print("Greetings " + person)
> pika greeter Xavier
Greetings Xavier
> pika help greeter
Greets the Master
- person
# Invokes the greeter with fixed argument
greeter: require("greeter.pika")
greeter("Magneto")
> pika invoker
Greetings Magneto
# Shows the invokers.pika documentation
invoker: require("invoker.pika")
print(invoker comments)
> pika documenter
Invokes the greeter with the fixed argument
# Creates a Cat from a Mammal prototype
Mammal: {
walk: {
print("Your mammal is walking")
}
}
Cat: Mammal()
Cat walk()
> pika cat
Your mammal is walking
# Creates a Tortoise from a partially filled
# prototype Reptile, created in time from
# Animal
name|
Animal: {legs, species, name|
walk: {
print("Your " + species + " " + name + " is walking on " + legs + "legs")
}
}
Reptile: Animal(4)
Tortoise: Reptile("Tortoise")
Tortoise("Donatello") walk()
> pika tortoise
Your Tortoise Donatello is walking on 4 legs
# Makes a conditional statement
# Note that "if" is just a function!
temperature|
if(temperature greater(20), {
print("Nice weather")
}, {
print("Getting cooler")
})
> pika conditional 14
Getting cooler
> pika conditional 25
Nice weather
# There is no return statement in pika
# Only callbacks
number|
multiplier: {value, callback|
callback(value * 7)
}
multiplier(number, {result|
print(result)
})
> pika return 8
56
# Buuut you are allowed to some syntactic sugar
#
# The 'x' as the second argument is actually a
# reserved word and means "assign callback
# value instead of call instance"
number|
3times: {value, callback|
callback(value * 3)
}
result: 3times(number, x)
print(result)
> pika sugar 4
12
# Every execution of a pika environment
# returns that execution as an instance
#
# Partial executions (some arguments are
# missing) mean that the block of the function
# is not evaluated: only properties are assigned
jump: {person, object|
print(person + " jumped the " + object)
}
aJump: jump("Oscar", "fridge")
print(aJump person)
print(aJump)
> pika jump
Oscar jumped the fridge
Oscar
{ person: "Oscar", object: fridge, print(person + " jumped the " + object)}
# Functions can provide an "argumentable object"
# experience
name|
missingName: {name, height: 1.74|}
solved: missingName(name)
print(solved)
> pika argumentable Jan
{ name: "Jan", height: 1.74 }
# The pipe as operator only means that
# declared variables before the pipe
# are required unless stated otherwise
#
# Variables declared after the pipe can be
# assigned as arguments but are not
# required for the calls in the block
# to be executed.
#
# Tip: Variables declared after the pipe
# are optional arguments
Measures: {height, width|
depth
}
cube: Measures(10, 10, 10)
sheet: Measures(29, 21)
print(cube)
print(sheet)
# The sheet can still be extruded!
extrude: sheet(5)
print(extrude depth)
> pika pipe
{ height: 10, width: 10, depth: 10 }
{ height: 29, width: 21}
5
# The dot operator references the current
# context. Two dots represents the parent
# context. This is useful to defined properties
# on the parent.
#
# Because there is no "self" or "this" in Pika
chimera: {
wingify: {howMany|
..wings: howMany
}
}
chimera wingify(2)
print(chimera wings)
> pika dot
2
# Variables are naturally overriden in the
# inner contexts. If not specified by "." or ".."
# or "..." (etc), the variables match the inner declaration.
#
# Declarations in inner contexts do not affect the outside
#
# This is most useful for exception handling. A basic
# try-catch implementation
raise: {message|
print("Oh my! " + message)
quit()
}
try: {block, fallback|
raise: {message|
# The "." to reference the raise instance...
# the "error" object in traditional programming
fallback(.)
}
block()
}
# Then you can capture an exception
try({
raise("Thunderstorm!")
},{captured|
print("I stopped this: " + captured message)
})
# ...and you can also give it the look and
# feel of a somewhat more regular try catch by taking
# advantage of partial executions
catch: try({
raise("Tsunami!")
})
catch({captured|
print("Dammed the " + captured)
})
> pika override
I stopped this: Oh My! Thunderstorm!
Dammed the Oh My! Tsunami!
# You can clone anything. If the arguments
# are not exhausted, you can clone anything
# just by executing it.
#
# For example, lets internationalize the
# "if" method
si: if()
om: if()
если: if()
# Lets get Japanese (google translated, don't judge)
# 20 is of course an object
20 大きい: 20 greater()
もし: if()
印刷: print()
# We can add a condition clause via property
# without affecting the regular "if"
もし condition: 20 大きい(10, x)
# And check if it is true
もし({
印刷("ピカは素晴らしいです!")
})
> ピカ japan
ピカは素晴らしいです!
# If the arguments have all been assigned
# and you still want to duplicate the object
# without executing its block, there is a hack:
# add an argument and do not fill it!
#
# Will add a "template" argument.
#
# Of, I forgot to mention: arguments are just `fillable`
# properties of the objects. Fillable is
# a primitive represented by an `O`
#
# No strange chars in Pika!
toDuplicate: {|
print("This should not be printed!")
}
toDuplicate template: O
clone: toDuplicate()
# You can remove the template property if you want
toDuplicate delete("template")
clone delete("template")
# Boureaucratic. But works
# You can make asynchronous calls. It's easy
> read("file.txt", {filename, contents|
print(filename + " has been read")
})
# Synchronous would be just
read("file.txt", {filename, contents|
print("Read again synchronously")
})
> pika async.pika
file.txt has been read
Read again synchronously
# Tidier code, but synchronous
readings: read("bigfile.txt", x)
# Asynchronous wildness
readings > read("bigfile.txt", later)
print(later)
# "readings" is an instance, but "later"
# is a "promise": will actually be completed later
#
# A synchronous call to "done" in the reading
# instance will execute the block when later is loaded
readings done({
print(later)
})
> pika later
{ filename: "bigfile.txt", contents: O}
{ filename: "bigfile.txt", contents: <...> }
# Pika accepts arrays. They are actually objects
# with numbers as property names.
#
# Tip: most Pika is syntactic sugar over a very
# simple program structure
array: ["y", "z"]
array 2: "a"
print(array)
> pika array
["y", "z", "a"]
# Want to intercept multiple callbacks?
# Does not matter why, Pika allows you
kindness: {animal, good, great|
good("Feed " + animal)
great("Take care of " + animal)
}
options = kindness("Ted", x, x)
print(options)
> pika kindness
{ good: "Feed Ted", great: "Take care of Ted" }
# Any string can be used as variable name,
# including string with spaces. To be able to use
# strings as variable names as arguments, you can
# explicit their pointer status by using the *
# When in the left side of ":" or after another
# variable, its status of property name is clear
rice: {
"cook some cups": {amount|
}
}
"the water": "is great"
print(*"the water")
> pika asterisk
is great