You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: content/_index.md
+4-4Lines changed: 4 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,7 +7,7 @@ title = 'About'
7
7
8
8
## Readable and concise concatenative programming
9
9
10
-
```
10
+
```cognate
11
11
~~ Fizzbuzz in Cognate
12
12
13
13
Def Multiple as (Zero? Modulo);
@@ -23,7 +23,7 @@ For each in Range 1 to 100 (Print Fizzbuzz)
23
23
24
24
Cognate is a project aiming to create a human readable programming language with as little syntax as possible. Where natural language programming usually uses many complex syntax rules, instead Cognate takes them away. What it adds is simple, a way to embed comments into statements.
25
25
26
-
```
26
+
```cognate
27
27
~~ Towers of Hanoi in Cognate
28
28
29
29
Def Move discs as (
@@ -45,7 +45,7 @@ Move 5 discs from "a" via "b" to "c"
45
45
46
46
As you can see, Cognate ignores words starting with lowercase letters, allowing them to be used to describe functionality and enhance readability. This makes Cognate codebases intuitive and maintainable.
47
47
48
-
```
48
+
```cognate
49
49
~~ Square numbers in Cognate
50
50
51
51
Def Square as (* Twin);
@@ -55,7 +55,7 @@ Print
55
55
56
56
Cognate is a stack-oriented programming language similar to Forth or Factor, except statements are evaluated right to left. This gives the expressiveness of concatenative programming as well as the readability of prefix notation. Statements can be delimited at arbitrary points, allowing them to read as sentences would in English.
Copy file name to clipboardExpand all lines: content/learn.md
+32-32Lines changed: 32 additions & 32 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,13 +29,13 @@ Alternatively, you can use the interactive web playground [here](https://cognate
29
29
## First Programs
30
30
31
31
32
-
```
32
+
```cognate
33
33
Print "Hello world!";
34
34
```
35
35
36
36
Fairly simple right? This example calls the `Print` function with one parameter - the string `"Hello world!"`. Now let's do another simple example, adding two numbers.
37
37
38
-
```
38
+
```cognate
39
39
Print + 2 3;
40
40
```
41
41
@@ -45,7 +45,7 @@ Wait what? That isn't how maths works!
45
45
Cognate doesn't care how maths works. Where in most programming languages, `+` would be an operator and would be used in the infix position, in Cognate `+` is a function. Like `Print`, the `+` function is called by being written before its arguments like shown above.
46
46
47
47
48
-
```
48
+
```cognate
49
49
Print - 10 36; ~~ Subtracts 10 from 36
50
50
```
51
51
@@ -55,7 +55,7 @@ Another thing to note is that the order of parameters for `-` and `/` are backwa
55
55
56
56
Let's have a more complex example, this subtracts 12 from 15 and then multiplies the result by 2.
57
57
58
-
```
58
+
```cognate
59
59
Print * 2 - 12 15;
60
60
```
61
61
@@ -71,7 +71,7 @@ By now you may have realised that Cognate is evaluating our programs backwards -
71
71
72
72
Cognate comes with functions to manipulate the stack. The simplest of these is `Twin`, which takes the top element from the stack, and puts it back on again - twice. The below snippet uses `Twin` to square a number by multiplying it by itself.
73
73
74
-
```
74
+
```cognate
75
75
Print * Twin 8;
76
76
```
77
77
@@ -81,14 +81,14 @@ Now we don't want to write this every time we square a number right? So let's cr
81
81
82
82
Functions in Cognate are defined using `Def` and the name of the function. The function body is put in brackets after this.
83
83
84
-
```
84
+
```cognate
85
85
Def Square (* Twin);
86
86
Print Square 8;
87
87
```
88
88
89
89
This is great, but it certainly could flow better. Cognate ignores words starting with lowercase letters, allowing them to be used as comments. This lets us write:
90
90
91
-
```
91
+
```cognate
92
92
Print the Square of 8;
93
93
```
94
94
@@ -98,19 +98,19 @@ In this example the readability isn't really improved much, but in more complex
98
98
By now you've probably noticed the semicolons. These delimit statements so that Cognate knows what order to evaluate functions in (remember that these are executed backwards). Definitions should also be terminated with semicolons. The stack persists between statements, letting us do things like this.
99
99
100
100
101
-
```
101
+
```cognate
102
102
8 ; Square ; Print ;
103
103
```
104
104
105
105
or this
106
106
107
-
```
107
+
```cognate
108
108
Square 8 ; Print ;
109
109
```
110
110
111
111
or this
112
112
113
-
```
113
+
```cognate
114
114
8 ; Print the Square ;
115
115
```
116
116
@@ -120,14 +120,14 @@ This flexible syntax allows Cognate programs to flow as if written in sentences.
120
120
121
121
Variables are defined in a fairly similar manner to functions using `Let` and their name. This takes a value from the stack, binding it to this name. Variables are referenced with the same syntax in which functions are called.
122
122
123
-
```
123
+
```cognate
124
124
Let X be 4;
125
125
Print X;
126
126
```
127
127
128
128
We can use variables to define functions that take named parameters - here's an alternate version of the `Square` function.
129
129
130
-
```
130
+
```cognate
131
131
Def Square as (
132
132
Let X;
133
133
* X X
@@ -136,7 +136,7 @@ Def Square as (
136
136
137
137
Notice that the last statement before a closing bracket does not need to be terminated with a semicolon. Also there is no return statement, since values are implicitly returned on the stack. This means we can actually define functions that return multiple values, such as the `Twin` function we saw earlier.
138
138
139
-
```
139
+
```cognate
140
140
Def Twin as (
141
141
Let X;
142
142
X X
@@ -148,23 +148,23 @@ Def Twin as (
148
148
149
149
Like most programming languages, Cognate has if statements and loops and all that jazz. The simplest form of control flow is `When`, which simply executes a block of code if given `True` or not if `False`.
150
150
151
-
```
151
+
```cognate
152
152
When == 1 1 (
153
153
Print "Who'd have guessed?"
154
154
);
155
155
```
156
156
157
157
There is also `Unless` that evaluates the block if given `False`. `While` takes a condition in brackets and evaluates the block of code until the condition is `False`. `Until`, you guessed it, is the opposite of `While` and runs until the condition is `True`.
158
158
159
-
```
159
+
```cognate
160
160
While (True) (
161
161
Print "This may well print forever"
162
162
);
163
163
```
164
164
165
165
What's with the second set of brackets? `When` doesn't have them, so why should `While`? This is because brackets denote blocks! These prevent code being instantly evaluated and instead push a reference onto the stack. Blocks also control variable scopes. We can evaluate a block using the `Do` function - which is how our control flow functions are implemented.
166
166
167
-
```
167
+
```cognate
168
168
Do (
169
169
Print "Hello from inside a block!"
170
170
);
@@ -176,7 +176,7 @@ This explains the syntax for functions: `Def` simply binds a block to a name, mu
176
176
Now that this (hopefully) makes some sense, we can finally introduce the `If` statement! `If` is a function that takes three parameters. The first is a boolean, if this is `True` then the second argument is returned. If not, the third argument is returned. We can chain `If`s together to have more complex control flow.
177
177
178
178
179
-
```
179
+
```cognate
180
180
Print
181
181
If == X 1 then "foo"
182
182
If == X 2 then "bar"
@@ -185,7 +185,7 @@ Print
185
185
186
186
We can combine this with `Do` to have conditional code execution.
187
187
188
-
```
188
+
```cognate
189
189
Do
190
190
If == X 1 then ( Print "foo" )
191
191
If == X 2 then ( Print "bar" )
@@ -194,7 +194,7 @@ Do
194
194
195
195
Now, lets use our knowledge of blocks to define our own control flow function `Thrice`, which should evaluate a block three times in a row. This demonstrates a different use of `Def` in which we bind a block from the stack.
196
196
197
-
```
197
+
```cognate
198
198
Def Thrice as (
199
199
Def F;
200
200
F F F
@@ -207,7 +207,7 @@ Thrice (
207
207
208
208
A more general version of this function, `Times` can be defined using recursion.
209
209
210
-
```
210
+
```cognate
211
211
Def Times (
212
212
Let N number of repetitions;
213
213
Def F function to repeat;
@@ -221,7 +221,7 @@ Times 5 (
221
221
222
222
Now you may see a small problem with this. If the user calls `Times` with a non-integer parameter it will loop forever - that won't do at all! We use the `Integer!` function to throw a type error if a decimal is given.
223
223
224
-
```
224
+
```cognate
225
225
Def Times (
226
226
Let N is Integer! number of repetitions;
227
227
Def F function to repeat;
@@ -235,7 +235,7 @@ We could also use the `Block!` function for `F` but we'll already get a type err
235
235
The `Times` function is also our first loop. We don't need to define it every time though as it's also in the standard library. Another loop is `While`.
236
236
237
237
238
-
```
238
+
```cognate
239
239
While (!= "done" Twin Input) (
240
240
Print
241
241
);
@@ -252,13 +252,13 @@ This loop is most useful in imperative code where intermediary values are passed
252
252
253
253
In Cognate, lists are generated using - you guessed it - a function. The `List` function takes a block as a parameter. It evaluates this block *in a new stack* and then returns that stack as a list.
254
254
255
-
```
255
+
```cognate
256
256
Print List (1 2 3 4 5);
257
257
```
258
258
259
259
This allows Cognate's list creation to be much more flexible than other languages - for example what if we wanted a list of 100 ones?
260
260
261
-
```
261
+
```cognate
262
262
Print List ( Times 100 (1) );
263
263
```
264
264
@@ -268,37 +268,37 @@ The three most fundamental list functions are `Push`, `First`, and `Rest`.
268
268
The `Push` function takes a value and a list as parameters, and returns the list with the value *pushed* to it's first element. `First` simply returns the first element of a list. `Rest` returns a list without its first element.
269
269
270
270
271
-
```
271
+
```cognate
272
272
Let L be Push "foo" to List ( "bar" "baz" );
273
273
Print First element of L;
274
274
Print Rest of L;
275
275
```
276
276
277
277
`Range` creates a list of numbers from a starting (inclusive) and an ending (exclusive) number. `For` is a higher order function that applied an operation to each element of a list - it is the loop for iterating over lists.
278
278
279
-
```
279
+
```cognate
280
280
Def Square as (* Twin);
281
281
For each in Range 1 to 20 (Print the Square);
282
282
```
283
283
284
284
`Map` is like `For` but the result of the computation is stored in a new list.
285
285
286
-
```
286
+
```cognate
287
287
Let Evens be Map (* 2) over Range 1 to 50;
288
288
Print Evens;
289
289
```
290
290
291
291
`Filter` applies a function to each element of a list also. This function should return a boolean - if this is `False` then the function is removed from the returned list.
292
292
293
-
```
293
+
```cognate
294
294
Let Even? be (Zero? Modulo 2);
295
295
Let Evens be Filter (Even?) over Range 1 to 100;
296
296
Print Evens;
297
297
```
298
298
299
299
The functional programmers reading this are likely expecting a Fold or Reduce function next - which applies an operation to a list with an accumulator. However Cognate needs no fold function, as `For` can store intermediary values on the stack, acting like a fold.
300
300
301
-
```
301
+
```cognate
302
302
Def Factorial as (
303
303
Let N be Integer!;
304
304
For each in Range 1 to N (*) from 1;
@@ -316,7 +316,7 @@ While storing state between loop iterations is very useful, in some cases you ju
316
316
The `Box` function takes a value and places it in a box. `Unbox` returns the item stored in a box. `Set` takes a box and a value as parameters and mutates the box to hold the value, updating all references to it.
317
317
318
318
319
-
```
319
+
```cognate
320
320
Let X be Box 1;
321
321
Print Unbox X; ~~ prints 1
322
322
@@ -326,7 +326,7 @@ Print Unbox X; ~~ prints 2
326
326
327
327
Boxes aren't limited to mutating variables, they can be used for any value.
328
328
329
-
```
329
+
```cognate
330
330
Let L be Map (Box) over Range 1 to 10;
331
331
Print L;
332
332
@@ -339,7 +339,7 @@ Print L;
339
339
340
340
While boxes may not seem as ergonomic as mutation in other languages, they are both more flexible than mutable variables and more predictable than implicit references. We can also easily extend mutation, like this:
0 commit comments