github.com/goplus/gop@v1.2.6/doc/docs.md (about)

     1  Go+ Quick Start
     2  ======
     3  
     4  Our vision is to **enable everyone to create production-level applications**.
     5  
     6  #### Easy to learn
     7  
     8  * Simple and easy to understand
     9  * Smaller syntax set than Python in best practices
    10  
    11  #### Ready for large projects
    12  
    13  * Derived from Go and easy to build large projects from its good engineering foundation
    14  
    15  The Go+ programming language is designed for engineering, STEM education, and data science.
    16  
    17  * **For engineering**: working in the simplest language that can be mastered by children.
    18  * **For STEM education**: studying an engineering language that can be used for work in the future.
    19  * **For data science**: communicating with engineers in the same language.
    20  
    21  ## How to install
    22  
    23  ### on Windows
    24  
    25  ```sh
    26  winget install goplus.gop
    27  ```
    28  
    29  ### on Debian/Ubuntu
    30  
    31  ```sh
    32  sudo bash -c ' echo "deb [trusted=yes] https://pkgs.goplus.org/apt/ /" > /etc/apt/sources.list.d/goplus.list'
    33  sudo apt update
    34  sudo apt install gop
    35  ```
    36  
    37  ### on RedHat/CentOS/Fedora
    38  
    39  ```sh
    40  sudo bash -c 'echo -e "[goplus]\nname=Go+ Repo\nbaseurl=https://pkgs.goplus.org/yum/\nenabled=1\ngpgcheck=0" > /etc/yum.repos.d/goplus.repo'
    41  sudo yum install gop
    42  ```
    43  
    44  ### on macOS/Linux (Homebrew)
    45  
    46  Install via [brew](https://brew.sh/)
    47  
    48  ```sh
    49  $ brew install goplus
    50  ```
    51  
    52  ### from source code
    53  
    54  Note: Requires go1.18 or later
    55  
    56  ```bash
    57  git clone https://github.com/goplus/gop.git
    58  cd gop
    59  
    60  # On mac/linux run:
    61  ./all.bash
    62  # On Windows run:
    63  all.bat
    64  ```
    65  
    66  Actually, `all.bash` and `all.bat` will use `go run cmd/make.go` underneath.
    67  
    68  
    69  ## Running in Go+ playground
    70  
    71  If you don't want install Go+, you can write your Go+ programs in Go+ playground. This is the fastest way to experience Go+.
    72  
    73  * Go+ playground based on Docker: https://play.goplus.org/
    74  * Go+ playground based on GopherJS: https://jsplay.goplus.org/
    75  
    76  And you can share your Go+ code with your friends.
    77  Here is my `Hello world` program:
    78  * https://play.goplus.org/p/AAh_gQAKAZR.
    79  
    80  
    81  ## Table of Contents
    82  
    83  <table>
    84      <tr><td width=33% valign=top>
    85  
    86  * [Hello world](#hello-world)
    87  * [Running a project folder](#running-a-project-folder-with-several-files)
    88  * [Comments](#comments)
    89  * [Variables](#variables)
    90  * [Go+ types](#go-types)
    91      * [Strings](#strings)
    92      * [Numbers](#numbers)
    93      * [Slices](#slices)
    94      * [Maps](#maps)
    95  * [Module imports](#module-imports)
    96  
    97  </td><td width=33% valign=top>
    98  
    99  * [Statements & expressions](#statements--expressions)
   100      * [If..else](#ifelse)
   101      * [For loop](#for-loop)
   102      * [Error handling](#error-handling)
   103  * [Functions](#functions)
   104      * [Returning multiple values](#returning-multiple-values)
   105      * [Variadic parameters](#variadic-parameters)
   106      * [Higher order functions](#higher-order-functions)
   107      * [Lambda expressions](#lambda-expressions)
   108  * [Structs](#structs)
   109  
   110  </td><td valign=top>
   111  
   112  * [Go/Go+ hybrid programming](#gogo-hybrid-programming)
   113      * [Run Go+ in watch mode](#run-go-in-watch-mode)
   114  * [Calling C from Go+](#calling-c-from-go)
   115  * [Data processing](#data-processing)
   116      * [Rational numbers](#rational-numbers)
   117      * [List comprehension](#list-comprehension)
   118      * [Select data from a collection](#select-data-from-a-collection)
   119      * [Check if data exists in a collection](#check-if-data-exists-in-a-collection)
   120  * [Unix shebang](#unix-shebang)
   121  * [Compatibility with Go](#compatibility-with-go)
   122  
   123  </td></tr>
   124  </table>
   125  
   126  
   127  ## Hello World
   128  
   129  Different from the function call style of most languages, Go+ recommends command style code:
   130  
   131  ```go
   132  println "Hello world"
   133  ```
   134  
   135  Save this snippet into a file named `hello.gop`. Now do: `gop run hello.gop`.
   136  
   137  Congratulations - you just wrote and executed your first Go+ program!
   138  
   139  You can compile a program without execution with `gop build hello.gop`.
   140  See `gop help` for all supported commands.
   141  
   142  [`println`](#println) is one of the few [built-in functions](#builtin-functions).
   143  It prints the value passed to it to standard output.
   144  
   145  To emphasize our preference for command style, we introduce `echo` as an alias for `println`:
   146  
   147  ```coffee
   148  echo "Hello world"
   149  ```
   150  
   151  See https://tutorial.goplus.org/hello-world for more details.
   152  
   153  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   154  
   155  
   156  ## Running a project folder with several files
   157  
   158  Suppose you have a folder with several .gop files in it, and you want 
   159  to compile them all into one program. Just do: `gop run .`.
   160  
   161  Passing parameters also works, so you can do:
   162  `gop run . --yourparams some_other_stuff`.
   163  
   164  Your program can then use the CLI parameters like this:
   165  
   166  ```go
   167  import "os"
   168  
   169  println os.Args
   170  ```
   171  
   172  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   173  
   174  
   175  ## Comments
   176  
   177  ```go
   178  # This is a single line comment.
   179  
   180  // This is a single line comment.
   181  
   182  /*
   183  This is a multiline comment.
   184  */
   185  ```
   186  
   187  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   188  
   189  
   190  ## Variables
   191  
   192  ```go
   193  name := "Bob"
   194  age := 20
   195  largeNumber := int128(1 << 65)
   196  println name, age
   197  println largeNumber
   198  ```
   199  
   200  Variables are declared and initialized with `:=`.
   201  
   202  The variable's type is inferred from the value on the right hand side.
   203  To choose a different type, use type conversion:
   204  the expression `T(v)` converts the value `v` to the
   205  type `T`.
   206  
   207  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   208  
   209  ### Initialization vs. assignment
   210  
   211  Note the (important) difference between `:=` and `=`.
   212  `:=` is used for declaring and initializing, `=` is used for assigning.
   213  
   214  ```go failcompile
   215  age = 21
   216  ```
   217  
   218  This code will not compile, because the variable `age` is not declared.
   219  All variables need to be declared in Go+.
   220  
   221  ```go
   222  age := 21
   223  ```
   224  
   225  The values of multiple variables can be changed in one line.
   226  In this way, their values can be swapped without an intermediary variable.
   227  
   228  ```go
   229  a, b := 0, 1
   230  a, b = b, a
   231  println a, b // 1, 0
   232  ```
   233  
   234  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   235  
   236  
   237  ## Go+ Types
   238  
   239  ### Primitive types
   240  
   241  ```go ignore
   242  bool
   243  
   244  int8    int16   int32   int    int64    int128
   245  uint8   uint16  uint32  uint   uint64   uint128
   246  
   247  uintptr // similar to C's size_t
   248  
   249  byte // alias for uint8
   250  rune // alias for int32, represents a Unicode code point
   251  
   252  string
   253  
   254  float32 float64
   255  
   256  complex64 complex128
   257  
   258  bigint bigrat
   259  
   260  unsafe.Pointer // similar to C's void*
   261  
   262  any // alias for Go's interface{}
   263  ```
   264  
   265  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   266  
   267  ### Strings
   268  
   269  ```go
   270  name := "Bob"
   271  println name.len  // 3
   272  println name[0]   // 66
   273  println name[1:3] // ob
   274  println name[:2]  // Bo
   275  println name[2:]  // b
   276  
   277  // or using octal escape `\###` notation where `#` is an octal digit
   278  println "\141a"   // aa
   279  
   280  // Unicode can be specified directly as `\u####` where # is a hex digit
   281  // and will be converted internally to its UTF-8 representation
   282  println "\u2605"  // ★
   283  ```
   284  
   285  String values are immutable. You cannot mutate elements:
   286  
   287  ```go failcompile
   288  s := "hello 🌎"
   289  s[0] = `H` // not allowed
   290  ```
   291  
   292  Note that indexing a string will produce a `byte`, not a `rune` nor another `string`.
   293  
   294  Strings can be easily converted to integers:
   295  
   296  ```go
   297  s := "12"
   298  a, err := s.int
   299  b := s.int! // will panic if s isn't a valid integer
   300  ```
   301  
   302  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   303  
   304  
   305  #### String operators
   306  
   307  ```go
   308  name := "Bob"
   309  bobby := name + "by" // + is used to concatenate strings
   310  println bobby // Bobby
   311  
   312  s := "Hello "
   313  s += "world"
   314  println s // Hello world
   315  ```
   316  
   317  Most Go+ operators must have values of the same type on both sides. You cannot concatenate an
   318  integer to a string:
   319  
   320  ```go failcompile
   321  age := 10
   322  println "age = " + age // not allowed
   323  ```
   324  
   325  We have to either convert `age` to a `string`:
   326  
   327  ```go
   328  age := 10
   329  println "age = " + age.string
   330  ```
   331  
   332  However, you can replace `age.string` to `"${age}"`:
   333  
   334  ```go
   335  age := 10
   336  println "age = ${age}"
   337  ```
   338  
   339  Here is a more complex example of `${expr}`:
   340  
   341  ```go
   342  host := "example.com"
   343  page := 0
   344  limit := 20
   345  println "https://${host}/items?page=${page+1}&limit=${limit}" // https://example.com/items?page=1&limit=20
   346  println "$$" // $
   347  ```
   348  
   349  
   350  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   351  
   352  
   353  ### Runes
   354  
   355  A `rune` represents a single Unicode character and is an alias for `int32`.
   356  
   357  ```go
   358  rocket := '🚀'
   359  println rocket         // 128640
   360  println string(rocket) // 🚀
   361  ```
   362  
   363  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   364  
   365  
   366  ### Numbers
   367  
   368  ```go
   369  a := 123
   370  ```
   371  
   372  This will assign the value of 123 to `a`. By default `a` will have the
   373  type `int`.
   374  
   375  You can also use hexadecimal, binary or octal notation for integer literals:
   376  
   377  ```go
   378  a := 0x7B
   379  b := 0b01111011
   380  c := 0o173
   381  ```
   382  
   383  All of these will be assigned the same value, 123. They will all have type
   384  `int`, no matter what notation you used.
   385  
   386  Go+ also supports writing numbers with `_` as separator:
   387  
   388  ```go
   389  num := 1_000_000 // same as 1000000
   390  ```
   391  
   392  If you want a different type of integer, you can use casting:
   393  
   394  ```go
   395  a := int64(123)
   396  b := uint8(12)
   397  c := int128(12345)
   398  ```
   399  
   400  Assigning floating point numbers works the same way:
   401  
   402  ```go
   403  f1 := 1.0
   404  f2 := float32(3.14)
   405  ```
   406  
   407  If you do not specify the type explicitly, by default float literals will have the type of `float64`.
   408  
   409  Float literals can also be declared as a power of ten:
   410  
   411  ```go
   412  f0 := 42e1   // 420
   413  f1 := 123e-2 // 1.23
   414  f2 := 456e+2 // 45600
   415  ```
   416  
   417  Go+ has built-in support for [rational numbers](#rational-numbers):
   418  
   419  ```go
   420  a := 1r << 200  // suffix `r` means `rational`
   421  b := bigint(1 << 200)
   422  ```
   423  
   424  And you can cast bool to number types (this is NOT supported in Go):
   425  
   426  ```go
   427  println int(true)       // 1
   428  println float64(true)   // 1
   429  println complex64(true) // (1+0i)
   430  ```
   431  
   432  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   433  
   434  
   435  ### Slices
   436  
   437  A slice is a collection of data elements of the same type. A slice literal is a
   438  list of expressions surrounded by square brackets. An individual element can be
   439  accessed using an *index* expression. Indexes start from `0`:
   440  
   441  ```go
   442  nums := [1, 2, 3]
   443  println nums      // [1 2 3]
   444  println nums.len  // 3
   445  println nums[0]   // 1
   446  println nums[1:3] // [2 3]
   447  println nums[:2]  // [1 2]
   448  println nums[2:]  // [3]
   449  
   450  nums[1] = 5
   451  println nums // [1 5 3]
   452  ```
   453  
   454  Type of a slice literal is infered automatically.
   455  
   456  ```go
   457  a := [1, 2, 3]   // []int
   458  b := [1, 2, 3.4] // []float64
   459  c := ["Hi"]      // []string
   460  d := ["Hi", 10]  // []any
   461  d := []          // []any
   462  ```
   463  
   464  And casting slice literals also works.
   465  
   466  ```go
   467  a := []float64([1, 2, 3]) // []float64
   468  ```
   469  
   470  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   471  
   472  
   473  ### Maps
   474  
   475  ```go
   476  a := {"Hello": 1, "xsw": 3}     // map[string]int
   477  b := {"Hello": 1, "xsw": 3.4}   // map[string]float64
   478  c := {"Hello": 1, "xsw": "Go+"} // map[string]any
   479  d := {}                         // map[string]any
   480  ```
   481  
   482  If a key is not found, a zero value is returned by default:
   483  
   484  ```go
   485  a := {"Hello": 1, "xsw": 3}
   486  c := {"Hello": 1, "xsw": "Go+"}
   487  println a["bad_key"] // 0
   488  println c["bad_key"] // <nil>
   489  ```
   490  
   491  You can also check, if a key is present, and get its value.
   492  
   493  ```go
   494  a := {"Hello": 1, "xsw": 3}
   495  if v, ok := a["xsw"]; ok {
   496      println "its value is", v
   497  }
   498  ```
   499  
   500  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   501  
   502  
   503  ## Module imports
   504  
   505  For information about creating a module, see [Modules](#modules).
   506  
   507  Modules can be imported using the `import` keyword:
   508  
   509  ```go
   510  import "strings"
   511  
   512  x := strings.NewReplacer("?", "!").Replace("Hello, world???")
   513  println x // Hello, world!!!
   514  ```
   515  
   516  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   517  
   518  
   519  ### Module import aliasing
   520  
   521  Any imported module name can be aliased:
   522  
   523  ```go
   524  import strop "strings"
   525  
   526  x := strop.NewReplacer("?", "!").Replace("Hello, world???")
   527  println x // Hello, world!!!
   528  ```
   529  
   530  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   531  
   532  
   533  ## Statements & expressions
   534  
   535  
   536  ### If..else
   537  
   538  In Go+, `if` statements are pretty straightforward and similar to most other languages.
   539  Unlike other C-like languages,
   540  there are no parentheses surrounding the condition and the braces are always required.
   541  
   542  ```go
   543  a := 10
   544  b := 20
   545  if a < b {
   546      println "a < b"
   547  } else if a > b {
   548      println "a > b"
   549  } else {
   550      println "a == b"
   551  }
   552  ```
   553  
   554  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   555  
   556  
   557  ### For loop
   558  
   559  Go+ has only one looping keyword: `for`, with several forms.
   560  
   561  #### `for`/`<-`
   562  
   563  This is the most common form. You can use it with a slice, map, numeric range or custom iterators.
   564  
   565  For information about creating a custom iterators, see [Custom iterators](#custom-iterators).
   566  
   567  ##### Slice `for`
   568  
   569  The `for value <- arr` form is used for going through elements of a slice.
   570  
   571  ```go
   572  numbers := [1, 3, 5, 7, 11, 13, 17]
   573  sum := 0
   574  for x <- numbers {
   575      sum += x
   576  }
   577  println sum // 57
   578  ```
   579  
   580  If an index is required, an alternative form `for index, value <- arr` can be used.
   581  
   582  ```go
   583  names := ["Sam", "Peter"]
   584  for i, name <- names {
   585      println i, name
   586      // 0 Sam
   587      // 1 Peter
   588  }
   589  ```
   590  
   591  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   592  
   593  
   594  ##### Map `for`
   595  
   596  ```go
   597  m := {"one": 1, "two": 2}
   598  for key, val <- m {
   599      println key, val
   600      // one 1
   601      // two 2
   602  }
   603  for key, _ <- m {
   604      println key
   605      // one
   606      // two
   607  }
   608  for val <- m {
   609      println val
   610      // 1
   611      // 2
   612  }
   613  ```
   614  
   615  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   616  
   617  
   618  ##### Range `for`
   619  
   620  You can use `range expression` (`start:end:step`) in for loop.
   621  
   622  ```go
   623  for i <- :5 {
   624      println i
   625      // 0
   626      // 1
   627      // 2
   628      // 3
   629      // 4
   630  }
   631  for i <- 1:5 {
   632      println i
   633      // 1
   634      // 2
   635      // 3
   636      // 4
   637  }
   638  for i <- 1:5:2 {
   639      println i
   640      // 1
   641      // 3
   642  }
   643  ```
   644  
   645  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   646  
   647  
   648  ##### `for`/`<-`/`if`
   649  
   650  All loops of `for`/`<-` form can have an optional `if` condition.
   651  
   652  ```go
   653  numbers := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
   654  for num <- numbers if num%3 == 0 {
   655      println num
   656      // 0
   657      // 3
   658      // 6
   659      // 9
   660  }
   661  
   662  for num <- :10 if num%3 == 0 {
   663      println num
   664      // 0
   665      // 3
   666      // 6
   667      // 9
   668  }
   669  ```
   670  
   671  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   672  
   673  
   674  #### Condition `for`
   675  
   676  ```go
   677  sum := 0
   678  i := 1
   679  for i <= 100 {
   680      sum += i
   681      i++
   682  }
   683  println sum // 5050
   684  ```
   685  
   686  This form of the loop is similar to `while` loops in other languages.
   687  The loop will stop iterating once the boolean condition evaluates to false.
   688  Again, there are no parentheses surrounding the condition, and the braces are always required.
   689  
   690  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   691  
   692  
   693  #### C `for`
   694  
   695  ```go
   696  for i := 0; i < 10; i += 2 {
   697      // Don't print 6
   698      if i == 6 {
   699          continue
   700      }
   701      println i
   702      // 0
   703      // 2
   704      // 4
   705      // 8
   706  }
   707  ```
   708  
   709  Finally, there's the traditional C style `for` loop. It's safer than the `while` form
   710  because with the latter it's easy to forget to update the counter and get
   711  stuck in an infinite loop.
   712  
   713  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   714  
   715  
   716  #### Bare `for`
   717  
   718  ```go
   719  for {
   720      // ...
   721  }
   722  ```
   723  
   724  The condition can be omitted, resulting in an infinite loop. You can use `break` or `return` to end the loop.
   725  
   726  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   727  
   728  
   729  ### Error handling
   730  
   731  We reinvent the error handling specification in Go+. We call them `ErrWrap expressions`:
   732  
   733  ```go
   734  expr! // panic if err
   735  expr? // return if err
   736  expr?:defval // use defval if err
   737  ```
   738  
   739  How to use them? Here is an example:
   740  
   741  ```go
   742  import (
   743      "strconv"
   744  )
   745  
   746  func add(x, y string) (int, error) {
   747      return strconv.Atoi(x)? + strconv.Atoi(y)?, nil
   748  }
   749  
   750  func addSafe(x, y string) int {
   751      return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0
   752  }
   753  
   754  println `add("100", "23"):`, add("100", "23")!
   755  
   756  sum, err := add("10", "abc")
   757  println `add("10", "abc"):`, sum, err
   758  
   759  println `addSafe("10", "abc"):`, addSafe("10", "abc")
   760  ```
   761  
   762  The output of this example is:
   763  
   764  ```
   765  add("100", "23"): 123
   766  add("10", "abc"): 0 strconv.Atoi: parsing "abc": invalid syntax
   767  
   768  ===> errors stack:
   769  main.add("10", "abc")
   770      /Users/xsw/tutorial/15-ErrWrap/err_wrap.gop:6 strconv.Atoi(y)?
   771  
   772  addSafe("10", "abc"): 10
   773  ```
   774  
   775  Compared to corresponding Go code, It is clear and more readable.
   776  
   777  And the most interesting thing is, the return error contains the full error stack. When we got an error, it is very easy to position what the root cause is.
   778  
   779  How these `ErrWrap expressions` work? See [Error Handling](https://github.com/goplus/gop/wiki/Error-Handling) for more information.
   780  
   781  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   782  
   783  
   784  ## Functions
   785  
   786  ```go
   787  func add(x int, y int) int {
   788      return x + y
   789  }
   790  
   791  println add(2, 3) // 5
   792  ```
   793  
   794  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   795  
   796  
   797  ### Returning multiple values
   798  
   799  ```go
   800  func foo() (int, int) {
   801      return 2, 3
   802  }
   803  
   804  a, b := foo()
   805  println a // 2
   806  println b // 3
   807  c, _ := foo() // ignore values using `_`
   808  ```
   809  
   810  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   811  
   812  
   813  ### Variadic parameters
   814  
   815  ```go
   816  func sum(a ...int) int {
   817      total := 0
   818      for x <- a {
   819          total += x
   820      }
   821      return total
   822  }
   823  
   824  println sum(2, 3, 5) // 10
   825  ```
   826  
   827  Output parameters can have names.
   828  
   829  ```go
   830  func sum(a ...int) (total int) {
   831      for x <- a {
   832          total += x
   833      }
   834      return // don't need return values if they are assigned
   835  }
   836  
   837  println sum(2, 3, 5) // 10
   838  ```
   839  
   840  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   841  
   842  
   843  ### Higher order functions
   844  
   845  Functions can also be parameters.
   846  
   847  ```go
   848  func square(x float64) float64 {
   849      return x*x
   850  }
   851  
   852  func abs(x float64) float64 {
   853      if x < 0 {
   854          return -x
   855      }
   856      return x
   857  }
   858  
   859  func transform(a []float64, f func(float64) float64) []float64 {
   860      return [f(x) for x <- a]
   861  }
   862  
   863  y := transform([1, 2, 3], square)
   864  println y // [1 4 9]
   865  
   866  z := transform([-3, 1, -5], abs)
   867  println z // [3 1 5]
   868  ```
   869  
   870  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   871  
   872  
   873  ### Lambda expressions
   874  
   875  You also can use `lambda expression` to define a anonymous function.
   876  
   877  ```go
   878  func transform(a []float64, f func(float64) float64) []float64 {
   879      return [f(x) for x <- a]
   880  }
   881  
   882  y := transform([1, 2, 3], x => x*x)
   883  println y // [1 4 9]
   884  
   885  z := transform([-3, 1, -5], x => {
   886      if x < 0 {
   887          return -x
   888      }
   889      return x
   890  })
   891  println z // [3 1 5]
   892  ```
   893  
   894  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   895  
   896  
   897  ## Structs
   898  
   899  ### Custom iterators
   900  
   901  #### For range of UDT
   902  
   903  ```go
   904  type Foo struct {
   905  }
   906  
   907  // Gop_Enum(proc func(val ValType)) or:
   908  // Gop_Enum(proc func(key KeyType, val ValType))
   909  func (p *Foo) Gop_Enum(proc func(key int, val string)) {
   910      // ...
   911  }
   912  
   913  foo := &Foo{}
   914  for k, v := range foo {
   915      println k, v
   916  }
   917  
   918  for k, v <- foo {
   919      println k, v
   920  }
   921  
   922  println {v: k for k, v <- foo}
   923  ```
   924  
   925  **Note: you can't use break/continue or return statements in for range of udt.Gop_Enum(callback).**
   926  
   927  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   928  
   929  
   930  #### For range of UDT2
   931  
   932  ```go
   933  type FooIter struct {
   934  }
   935  
   936  // (Iterator) Next() (val ValType, ok bool) or:
   937  // (Iterator) Next() (key KeyType, val ValType, ok bool)
   938  func (p *FooIter) Next() (key int, val string, ok bool) {
   939      // ...
   940  }
   941  
   942  type Foo struct {
   943  }
   944  
   945  // Gop_Enum() Iterator
   946  func (p *Foo) Gop_Enum() *FooIter {
   947      // ...
   948  }
   949  
   950  foo := &Foo{}
   951  for k, v := range foo {
   952      println k, v
   953  }
   954  
   955  for k, v <- foo {
   956      println k, v
   957  }
   958  
   959  println {v: k for k, v <- foo}
   960  ```
   961  
   962  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   963  
   964  
   965  ### Deduce struct type
   966  
   967  ```go
   968  type Config struct {
   969      Dir   string
   970      Level int
   971  }
   972  
   973  func foo(conf *Config) {
   974      // ...
   975  }
   976  
   977  foo {Dir: "/foo/bar", Level: 1}
   978  ```
   979  
   980  Here `foo {Dir: "/foo/bar", Level: 1}` is equivalent to `foo(&Config{Dir: "/foo/bar", Level: 1})`. However, you can't replace `foo(&Config{"/foo/bar", 1})` with `foo {"/foo/bar", 1}`, because it is confusing to consider `{"/foo/bar", 1}` as a struct literal.
   981  
   982  You also can omit struct types in a return statement. For example:
   983  
   984  ```go
   985  type Result struct {
   986      Text string
   987  }
   988  
   989  func foo() *Result {
   990      return {Text: "Hi, Go+"} // return &Result{Text: "Hi, Go+"}
   991  }
   992  ```
   993  
   994  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
   995  
   996  
   997  ### Overload operators
   998  
   999  ```go
  1000  import "math/big"
  1001  
  1002  type MyBigInt struct {
  1003      *big.Int
  1004  }
  1005  
  1006  func Int(v *big.Int) MyBigInt {
  1007      return MyBigInt{v}
  1008  }
  1009  
  1010  func (a MyBigInt) + (b MyBigInt) MyBigInt { // binary operator
  1011      return MyBigInt{new(big.Int).Add(a.Int, b.Int)}
  1012  }
  1013  
  1014  func (a MyBigInt) += (b MyBigInt) {
  1015      a.Int.Add(a.Int, b.Int)
  1016  }
  1017  
  1018  func -(a MyBigInt) MyBigInt { // unary operator
  1019      return MyBigInt{new(big.Int).Neg(a.Int)}
  1020  }
  1021  
  1022  a := Int(1r)
  1023  a += Int(2r)
  1024  println a + Int(3r)
  1025  println -a
  1026  ```
  1027  
  1028  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1029  
  1030  
  1031  ### Auto property
  1032  
  1033  Let's see an example written in Go+:
  1034  
  1035  ```go
  1036  import "gop/ast/goptest"
  1037  
  1038  doc := goptest.New(`... Go+ code ...`)!
  1039  
  1040  println doc.Any().FuncDecl().Name()
  1041  ```
  1042  
  1043  In many languages, there is a concept named `property` who has `get` and `set` methods.
  1044  
  1045  Suppose we have `get property`, the above example will be:
  1046  
  1047  ```go
  1048  import "gop/ast/goptest"
  1049  
  1050  doc := goptest.New(`... Go+ code ...`)!
  1051  
  1052  println doc.any.funcDecl.name
  1053  ```
  1054  
  1055  In Go+, we introduce a concept named `auto property`. It is a `get property`, but is implemented automatically. If we have a method named `Bar()`, then we will have a `get property` named `bar` at the same time.
  1056  
  1057  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1058  
  1059  
  1060  ## Go/Go+ hybrid programming
  1061  
  1062  This is an example to show how to mix Go/Go+ code in the same package.
  1063  
  1064  In this example, we have a Go source file named `a.go`:
  1065  
  1066  ```go
  1067  package main
  1068  
  1069  import "fmt"
  1070  
  1071  func p(a interface{}) {
  1072      sayMix()
  1073      fmt.Println("Hello,", a)
  1074  }
  1075  ```
  1076  
  1077  And we have a Go+ source file named `b.gop`:
  1078  
  1079  ```go
  1080  func sayMix() {
  1081      println "Mix Go and Go+"
  1082  }
  1083  
  1084  p "world"
  1085  ```
  1086  
  1087  You can see that Go calls a Go+ function named `sayMix`, and Go+ calls a Go function named `p`. As you are used to in Go programming, this kind of circular reference is allowed.
  1088  
  1089  Run `gop run .` to see the output of this example:
  1090  
  1091  ```
  1092  Mix Go and Go+
  1093  Hello, world
  1094  ```
  1095  
  1096  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1097  
  1098  
  1099  ### Run Go+ in watch mode
  1100  
  1101  The `gop` command can run in watch mode so that everytime a Go+ file is changed it is transpiled to a Go file:
  1102  
  1103  ```
  1104  gop watch [-gentest] [dir]
  1105  ```
  1106  
  1107  By default `gop watch` does not convert test files (normally ending with `_test.gop`). You can specify `-gentest` flag to force converting all Go+ files.
  1108  
  1109  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1110  
  1111  
  1112  ## Calling C from Go+
  1113  
  1114  - The `gop c` command (equivalent to the stand-alone `c2go` command) can be used to convert a C project to a Go project.
  1115  - `import "C"` and `import "C/xxx"` are used to import a C project converted by c2go. where `import "C"` is short for `import "C/github.com/goplus/libc"`.
  1116  - The `C"xxx"` syntax represents C-style string constants.
  1117  
  1118  Here is [an example to show how Go+ interacts with C](https://github.com/goplus/gop/tree/v1.1/testdata/helloc2go).
  1119  
  1120  ```go
  1121  import "C"
  1122  
  1123  C.printf C"Hello, c2go!\n"
  1124  C.fprintf C.stderr, C"Hi, %7.1f\n", 3.14
  1125  ```
  1126  
  1127  In this example we call two C standard functions `printf` and `fprintf`, passing a C variable `stderr` and two C strings in the form of `C"xxx"` (a Go+ syntax to represent C-style strings).
  1128  
  1129  Run `gop run .` to see the output of this example:
  1130  
  1131  ```
  1132  Hello, c2go!
  1133  Hi,     3.1
  1134  ```
  1135  
  1136  Of course, the current Go+ support for C is only a preview version, not to the extent that it is actually available in engineering. As far as libc is concerned, the current migration progress is only about 5%, and it is just the beginning.
  1137  
  1138  In the upcoming Go+ v1.2 version planning, complete support for C is listed as a top priority. Of course, support for cgo and Go templates is also under planning, which is a crucial capability enhancement for Go/Go+ hybrid projects.
  1139  
  1140  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1141  
  1142  
  1143  ## Data processing
  1144  
  1145  ### Rational numbers
  1146  
  1147  We introduce rational numbers as primitive Go+ types. We use suffix `r` to denote rational literals. For example, `1r << 200` means a big int whose value is equal to 2<sup>200</sup>.
  1148  
  1149  ```go
  1150  a := 1r << 200
  1151  b := bigint(1 << 200)
  1152  ```
  1153  
  1154  By default, `1r` will have the type of `bigint`.
  1155  
  1156  And `4/5r` means the rational constant `4/5`.
  1157  It will have the type of `bigrat`.
  1158  
  1159  ```go
  1160  a := 4/5r
  1161  b := a - 1/3r + 3 * 1/2r
  1162  println a, b // 4/5 59/30
  1163  ```
  1164  
  1165  Casting rational numbers works like other [primitive types](#primitive-types):
  1166  
  1167  ```go
  1168  a := 1r
  1169  b := bigrat(1r)
  1170  c := bigrat(1)
  1171  println a/3 // 0
  1172  println b/3 // 1/3
  1173  println c/3 // 1/3
  1174  ```
  1175  
  1176  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1177  
  1178  
  1179  ### List comprehension
  1180  
  1181  ```go
  1182  a := [x*x for x <- [1, 3, 5, 7, 11]]
  1183  b := [x*x for x <- [1, 3, 5, 7, 11] if x > 3]
  1184  c := [i+v for i, v <- [1, 3, 5, 7, 11] if i%2 == 1]
  1185  
  1186  arr := [1, 2, 3, 4, 5, 6]
  1187  d := [[a, b] for a <- arr if a < b for b <- arr if b > 2]
  1188  
  1189  x := {x: i for i, x <- [1, 3, 5, 7, 11]}
  1190  y := {x: i for i, x <- [1, 3, 5, 7, 11] if i%2 == 1}
  1191  z := {v: k for k, v <- {1: "Hello", 3: "Hi", 5: "xsw", 7: "Go+"} if k > 3}
  1192  ```
  1193  
  1194  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1195  
  1196  
  1197  ### Select data from a collection
  1198  
  1199  ```go
  1200  type student struct {
  1201      name  string
  1202      score int
  1203  }
  1204  
  1205  students := [student{"Ken", 90}, student{"Jason", 80}, student{"Lily", 85}]
  1206  
  1207  unknownScore, ok := {x.score for x <- students if x.name == "Unknown"}
  1208  jasonScore := {x.score for x <- students if x.name == "Jason"}
  1209  
  1210  println unknownScore, ok // 0 false
  1211  println jasonScore // 80
  1212  ```
  1213  
  1214  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1215  
  1216  
  1217  ### Check if data exists in a collection
  1218  
  1219  ```go
  1220  type student struct {
  1221      name  string
  1222      score int
  1223  }
  1224  
  1225  students := [student{"Ken", 90}, student{"Jason", 80}, student{"Lily", 85}]
  1226  
  1227  hasJason := {for x <- students if x.name == "Jason"} // is any student named Jason?
  1228  hasFailed := {for x <- students if x.score < 60}     // is any student failed?
  1229  ```
  1230  
  1231  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1232  
  1233  
  1234  ## Unix shebang
  1235  
  1236  You can use Go+ programs as shell scripts now. For example:
  1237  
  1238  ```go
  1239  #!/usr/bin/env -S gop run
  1240  
  1241  println "Hello, Go+"
  1242  
  1243  println 1r << 129
  1244  println 1/3r + 2/7r*2
  1245  
  1246  arr := [1, 3, 5, 7, 11, 13, 17, 19]
  1247  println arr
  1248  println [x*x for x <- arr, x > 3]
  1249  
  1250  m := {"Hi": 1, "Go+": 2}
  1251  println m
  1252  println {v: k for k, v <- m}
  1253  println [k for k, _ <- m]
  1254  println [v for v <- m]
  1255  ```
  1256  
  1257  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1258  
  1259  
  1260  ## Compatibility with Go
  1261  
  1262  All Go features will be supported (including partially support `cgo`, see [below](#bytecode-vs-go-code)).
  1263  
  1264  **All Go packages (even these packages use `cgo`) can be imported by Go+.**
  1265  
  1266  ```coffee
  1267  import (
  1268      "fmt"
  1269      "strings"
  1270  )
  1271  
  1272  x := strings.NewReplacer("?", "!").Replace("hello, world???")
  1273  fmt.Println "x:", x
  1274  ```
  1275  
  1276  **And all Go+ packages can also be imported in Go programs. What you need to do is just using `gop` command instead of `go`.**
  1277  
  1278  First, let's make a directory named `14-Using-goplus-in-Go`.
  1279  
  1280  Then write a Go+ package named [foo](https://github.com/goplus/tutorial/tree/main/14-Using-goplus-in-Go/foo) in it:
  1281  
  1282  ```go
  1283  package foo
  1284  
  1285  func ReverseMap(m map[string]int) map[int]string {
  1286      return {v: k for k, v <- m}
  1287  }
  1288  ```
  1289  
  1290  Then use it in a Go package [14-Using-goplus-in-Go/gomain](https://github.com/goplus/tutorial/tree/main/14-Using-goplus-in-Go/gomain):
  1291  
  1292  ```go
  1293  package main
  1294  
  1295  import (
  1296      "fmt"
  1297  
  1298      "github.com/goplus/tutorial/14-Using-goplus-in-Go/foo"
  1299  )
  1300  
  1301  func main() {
  1302      rmap := foo.ReverseMap(map[string]int{"Hi": 1, "Hello": 2})
  1303      fmt.Println(rmap)
  1304  }
  1305  ```
  1306  
  1307  How to build this example? You can use:
  1308  
  1309  ```bash
  1310  gop install -v ./...
  1311  ```
  1312  
  1313  Go [github.com/goplus/tutorial/14-Using-goplus-in-Go](https://github.com/goplus/tutorial/tree/main/14-Using-goplus-in-Go) to get the source code.
  1314  
  1315  <h5 align="right"><a href="#table-of-contents">⬆ back to toc</a></h5>
  1316  
  1317  
  1318  ## Bytecode vs. Go code
  1319  
  1320  Go+ supports bytecode backend and Go code generation.
  1321  
  1322  When we use `gop` command, it generates Go code to covert Go+ package into Go packages.
  1323  
  1324  ```bash
  1325  gop run     # Run a Go+ program
  1326  gop install # Build Go+ files and install target to GOBIN
  1327  gop build   # Build Go+ files
  1328  gop test    # Test Go+ packages
  1329  gop fmt     # Format Go+ packages
  1330  gop clean   # Clean all Go+ auto generated files
  1331  gop go      # Convert Go+ packages into Go packages
  1332  ```
  1333  
  1334  When we use [`igop`](https://github.com/goplus/igop) command, it generates bytecode to execute.
  1335  
  1336  ```bash
  1337  igop  # Run a Go+ program
  1338  ```
  1339  
  1340  In bytecode mode, Go+ doesn't support `cgo`. However, in Go-code-generation mode, Go+ fully supports `cgo`.