mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-12-23 09:41:36 +00:00
[phix/en] create (#4131)
This commit is contained in:
parent
389f2c2956
commit
ab75eeff40
451
phix.html.markdown
Normal file
451
phix.html.markdown
Normal file
@ -0,0 +1,451 @@
|
||||
---
|
||||
language: Phix
|
||||
contributors:
|
||||
- ["pxtom", "https://gitgub.com/pxtom"]
|
||||
filename: learnphix.exw
|
||||
---
|
||||
|
||||
```
|
||||
-- single line comment
|
||||
|
||||
// single line comment
|
||||
|
||||
/* multi-
|
||||
line comment */
|
||||
|
||||
// Start programming immediately
|
||||
|
||||
-- write using UTF8; save as: hello.ex
|
||||
-- use ? for output
|
||||
|
||||
? "😍 hello , 😎 world!"
|
||||
? sqrt(2+2)
|
||||
|
||||
// Interpret your program
|
||||
/*
|
||||
p hello */
|
||||
|
||||
// Compile your program
|
||||
/*
|
||||
p -c hello */
|
||||
|
||||
// Coding mistakes receive gentle help messages
|
||||
/*
|
||||
string line
|
||||
line = 5
|
||||
^ type error (storing atom in string) */
|
||||
|
||||
// Every literal value, constant, and variable is an ''object''
|
||||
|
||||
-- a literal object
|
||||
? "hello"
|
||||
? PI
|
||||
? { "hello", PI }
|
||||
|
||||
-- a named variable object
|
||||
object X
|
||||
X = "hello"
|
||||
X = PI
|
||||
X = { "hello", PI }
|
||||
|
||||
-- a named constant object
|
||||
constant myPI = 22/7
|
||||
|
||||
// Everything is an ''object'', just two fundemental kinds
|
||||
/*
|
||||
┌────────────────────▄
|
||||
┌─┤ object █─┐
|
||||
│ └─▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄█ │
|
||||
│ │
|
||||
"atom" "container" */
|
||||
|
||||
number x = 3.14159 sequence s = { "hello", PI }
|
||||
integer y = 3 string txt = "hello"
|
||||
|
||||
-- simplify,
|
||||
-- and use only two primitives
|
||||
number x1=3.14156, y1=3
|
||||
sequence s1={"hello",PI}, txt1="hello"
|
||||
|
||||
-- simplify even more,
|
||||
-- and use just one primitive
|
||||
object x2=3.14156, y2=3, s2={"hello",PI}, txt2="hello"
|
||||
|
||||
// Elegant data-type design
|
||||
|
||||
-- invent your own "type"
|
||||
-- organize with "struct" or "class"
|
||||
/*
|
||||
╔═══════════════════════════════╗
|
||||
║ ┌─────────────────────────┐ ║
|
||||
║ │ ┌───────────▄ │ ║
|
||||
║ │ ┌─┤ object █─┐ │ ║
|
||||
║ │ │ └─▄▄▄▄▄▄▄▄▄▄█ │ │ ║
|
||||
║ │ │ │ │ ║
|
||||
║ │ number sequence │ ║
|
||||
║ │ │ │ │ ║
|
||||
║ │ integer string │ ║
|
||||
║ └──────── type ───────────┘ ║
|
||||
║ ║
|
||||
╚════════ struct ║
|
||||
class ════════════════╝
|
||||
*/
|
||||
|
||||
// Syntax is consistant: "keyword...end keyword"
|
||||
|
||||
-- no invisible syntax or extra rules needed.
|
||||
|
||||
// loop
|
||||
-- while ... end while
|
||||
|
||||
integer index = 1
|
||||
while index <= 5 do
|
||||
? index
|
||||
index += 1
|
||||
end while
|
||||
|
||||
// loop
|
||||
-- for ... end for
|
||||
|
||||
for i=5 to 1 by -1 do
|
||||
? i
|
||||
end for
|
||||
|
||||
// conditional
|
||||
-- if ... end if
|
||||
|
||||
number p = 4
|
||||
if p < 1 then
|
||||
? "p is a small number"
|
||||
elsif p > 10 then
|
||||
? "p is a large number"
|
||||
else
|
||||
? "p is inbetween"
|
||||
end if
|
||||
|
||||
// conditional
|
||||
-- switch ... end switch
|
||||
|
||||
object ch = prompt_string("enter one character: " )
|
||||
switch ch
|
||||
case "a": ? "ch is a"
|
||||
case "b": ? "ch is b"
|
||||
case "c": ? "ch is c"
|
||||
default: ? "ch is something else"
|
||||
end switch
|
||||
|
||||
// Operators are always consistant; never overloaded.
|
||||
|
||||
-- the + operator ''always adds''
|
||||
? 2+7
|
||||
? 'A' + 32
|
||||
|
||||
-- the & operator ''always concatenates''
|
||||
? 2 & 7 --> {2,7}
|
||||
? "cat" & " " & "dog" --> "cat dog"
|
||||
? {1,2,3} & "fish" --> {1,2,3} & "fish"
|
||||
pp( {1,2,3} & "fish" ) --> {1,2,3,102'f',105'i',115's',104'h'}
|
||||
|
||||
// Use ''sq_'' functions to span entire containers.
|
||||
|
||||
? sq_add( {1,2,3}, 10 ) --> {11,12,13}
|
||||
? sq_sqrt( {4,9,16} ) --> {2,3,4}
|
||||
|
||||
// Functions must return a value
|
||||
|
||||
function add2( number x, number y )
|
||||
number sum = x + y
|
||||
return sum
|
||||
end function
|
||||
? add2( 4, 9 )
|
||||
|
||||
// Procedures do not return a value
|
||||
|
||||
procedure sum_all( sequence lst )
|
||||
number sum = 0
|
||||
for i=1 to length(lst) do
|
||||
sum += lst[i]
|
||||
end for
|
||||
? sum
|
||||
end procedure
|
||||
sum_all( {1,3,9,11} )
|
||||
|
||||
// Recursion and mutal recursion are permitted
|
||||
|
||||
function factorial(number n)
|
||||
if n == 0 then
|
||||
return 1
|
||||
end if
|
||||
if n<0 then
|
||||
return "error, no negative numbers for factorials"
|
||||
end if
|
||||
return n * factorial(n - 1)
|
||||
end function
|
||||
? factorial(5)
|
||||
|
||||
// User defined data-types
|
||||
|
||||
-- defined like a function: type ... end type
|
||||
-- they are fully programmable; add your own features
|
||||
|
||||
type positive( number x )
|
||||
if not integer(x) then
|
||||
? "use integers for factorials"
|
||||
return False
|
||||
end if
|
||||
if x < 0 then
|
||||
? "error, no negative numbers for factorials"
|
||||
return False
|
||||
end if
|
||||
return True
|
||||
end type
|
||||
|
||||
-- use them to declare variables and parameters
|
||||
|
||||
function factorial2( positive n )
|
||||
if n == 0 then return 1 end if
|
||||
return n * factorial2(n-1)
|
||||
end function
|
||||
? factorial(5)
|
||||
|
||||
-- to catch errors, and recover, use: try ... end try
|
||||
|
||||
try
|
||||
? factorial2( -5 )
|
||||
catch e
|
||||
? "that was a mistake"
|
||||
end try
|
||||
|
||||
// Sequences are versatile
|
||||
|
||||
-- multiple assignment
|
||||
number a, b, c
|
||||
{a,b,c} = { -100, -200/-2, -300*3 }
|
||||
? a --> -100
|
||||
? b --> 100
|
||||
? c --> -900
|
||||
|
||||
-- swapping values
|
||||
? a --> -100
|
||||
? c --> -900
|
||||
{a,c} = {c,a}
|
||||
? a --> -900
|
||||
? c --> -100
|
||||
|
||||
|
||||
// Symmetrical one-based indexing does it all
|
||||
|
||||
-- both sequence and string are mutable and work alike
|
||||
|
||||
-- 1 2 3 4 5 -- index head to tail
|
||||
s = { 10, 20, 30, 40, 50 }
|
||||
-- -5 -4 -3 -2 -1 -- index tail to head
|
||||
|
||||
// one item
|
||||
? s[ 2]
|
||||
? s[-4]
|
||||
-- output for both is:
|
||||
-----> 20
|
||||
|
||||
// slice with one item
|
||||
? s[ 2.. 2]
|
||||
? s[-4..-4]
|
||||
-- output for both is:
|
||||
-----> {20}
|
||||
|
||||
// inclusive slice
|
||||
? s[ 2.. 4]
|
||||
? s[-4..-2]
|
||||
-- output for both is:
|
||||
-----> {20,30,40}
|
||||
|
||||
// empty sequence
|
||||
? s[3 .. 2]
|
||||
? s[-3..-4]
|
||||
-- output for both is:
|
||||
-----> {}
|
||||
|
||||
// insert
|
||||
s[3..2] = {99}
|
||||
? s
|
||||
-----> {10,20,99,30,40,50}
|
||||
|
||||
// prepend and append
|
||||
s = { 10,20,30,40,50 }
|
||||
|
||||
s[ 1..0] = {0} -- prepend
|
||||
s[$+1..$] = {6} -- append
|
||||
|
||||
? s
|
||||
-----> {0,10,20,99,30,40,50,6}
|
||||
|
||||
s[0..-1] = {9999} -- append
|
||||
|
||||
? s
|
||||
-----> {0,10,20,99,30,40,50,6,9999}
|
||||
|
||||
// delete
|
||||
s = { 10,20,30,40,50 }
|
||||
|
||||
s[2..2] = {} -- item deleted
|
||||
? s
|
||||
-----> {10,30,40,50}
|
||||
|
||||
s[2..3] = {} -- slice deleted
|
||||
? s
|
||||
-----> {10,50}
|
||||
|
||||
// Learn and reuse; you keep what you learn.
|
||||
|
||||
s = { 1,3,5,7 }
|
||||
txt = "jello"
|
||||
|
||||
-- "find" locates one item in either a sequence or a string
|
||||
? find( 3, s ) --> 2
|
||||
? find( 'e', txt ) --> 2
|
||||
|
||||
-- "match" locates a slice in either a sequence or a string
|
||||
? match( {5,7}, s ) -- > 3
|
||||
? match( "ll", txt ) --> 3
|
||||
|
||||
// Look back at the examples, Phix is generic!
|
||||
|
||||
// Batteries are installed
|
||||
|
||||
? sort( {2, 54,6,4, 0} )
|
||||
? upper( "cat" )
|
||||
? log( 10.4 )
|
||||
? trunc(1.4) -- 1
|
||||
? floor(1.4) -- 1
|
||||
? trunc(-1.4) -- -1
|
||||
? floor(-1.4) -- -2
|
||||
|
||||
// Batteries are included
|
||||
|
||||
include builtins/regex.e
|
||||
|
||||
string str = "say hello and smile"
|
||||
str = gsub( `s...e`, str, "😍" )
|
||||
? str --> "say hello and 😍"
|
||||
|
||||
// Yes, sequences are "powerful"
|
||||
|
||||
function odd(integer a) return remainder(a,2)=1 end function
|
||||
function even(integer a) return remainder(a,2)=0 end function
|
||||
|
||||
? tagset(10) --> {1,2,3,4,5,6,7,8,9,10}
|
||||
? filter(tagset(10),odd) --> {1,3,5,7,9}
|
||||
? filter(tagset(10),even) --> {2,4,6,8,10}
|
||||
|
||||
// A ''struct'' provides named fields, type-checking, and dot notation
|
||||
|
||||
struct point
|
||||
number x = 0
|
||||
number y = 0
|
||||
end struct
|
||||
|
||||
procedure show( point q )
|
||||
printf(1, "(%g,%g)", { q.x, q.y } )
|
||||
end procedure
|
||||
|
||||
point p1 = new()
|
||||
show(p1)
|
||||
--> (0,0)
|
||||
|
||||
p1.x = 3
|
||||
p1.y = 5
|
||||
show( p1 )
|
||||
--> (3,5)
|
||||
|
||||
// A ''class'' adds methods and scope control
|
||||
|
||||
class pair
|
||||
public number x = 0
|
||||
public number y = 0
|
||||
|
||||
procedure show( )
|
||||
printf(1, "(%g,%g)", { this.x, this.y } )
|
||||
end procedure
|
||||
end class
|
||||
|
||||
pair p2 = new()
|
||||
p2.show()
|
||||
--> (0,0)
|
||||
|
||||
p2.x = 3
|
||||
p2.y = 5
|
||||
p2.show()
|
||||
--> (3,5)
|
||||
|
||||
// Inherit and compose
|
||||
|
||||
class Pair -- any 2 objects
|
||||
public sequence xy
|
||||
public integer x,y
|
||||
function get_x()
|
||||
return xy[1]
|
||||
end function
|
||||
|
||||
function get_y()
|
||||
return xy[2]
|
||||
end function
|
||||
end class
|
||||
|
||||
type pos_seq(sequence x)
|
||||
return min(x) >= 0
|
||||
end type
|
||||
|
||||
class Point extends Pair
|
||||
public pos_seq loc -- any two numbers >= 0
|
||||
|
||||
procedure set_loc(object x)
|
||||
this.xy = {x[1],x[2]}
|
||||
end procedure
|
||||
end class
|
||||
|
||||
class Rectangle extends Point
|
||||
public Point tlc,brc --top_left, bottom_right corners;
|
||||
public sequence size
|
||||
|
||||
function get_size()
|
||||
this.size = {brc.x-tlc.x , brc.y-tlc.y}
|
||||
return this.size
|
||||
end function
|
||||
end class
|
||||
|
||||
Point p1a = new() p1a.loc = {50,10}
|
||||
Point p2a = new() p2a.loc = {300,200}
|
||||
|
||||
Rectangle r = new()
|
||||
r.tlc = p1a
|
||||
r.brc = p2a
|
||||
? r -- {"struct","Rectangle",4,1}
|
||||
? r.tlc -- {"struct","Point",3,3}
|
||||
|
||||
? r.size --> {250,190}
|
||||
? r.get_size() --> {250,190}
|
||||
```
|
||||
|
||||
Phix does not (although most can be emulated) directly support
|
||||
operator|builtin|function overloading, lambda expressions, closures,
|
||||
currying, eval, partial function application, function composition,
|
||||
function prototyping, monads, generators, anonymous recursion,
|
||||
the Y combinator, aspect oriented programming, interfaces, delegates,
|
||||
first class environments, implicit type conversion
|
||||
(of the destructive kind), interactive programming, inverted syntax,
|
||||
list comprehensions, metaprogramming, pointers
|
||||
(other than to raw allocated memory), topic variables,
|
||||
enforced singletons, safe mode, s-expressions,
|
||||
or formal proof construction.
|
||||
|
||||
The author wryly comments:
|
||||
|
||||
''That should both scare off and attract the right people''.
|
||||
|
||||
|
||||
## References
|
||||
|
||||
* [http://phix.x10.mx](http://phix.x10.mx)
|
||||
* [Source code](https://github.com/petelomax/Phix)
|
||||
* [Forum](https://openeuphoria.org/forum/index.wc)
|
||||
* [Rosetta Code](https://rosettacode.org/wiki/Category:Phix)
|
Loading…
Reference in New Issue
Block a user