Skip to content

Commit

Permalink
optimize code in features
Browse files Browse the repository at this point in the history
  • Loading branch information
nighca committed Dec 1, 2021
1 parent 2a30c73 commit 242bbe2
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 55 deletions.
18 changes: 12 additions & 6 deletions goplus.org/components/Code/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import styles from './style.module.scss'

const langGop = 'gop'

// `gop|raw` means language: `gop`, while not interactive (runnable / editable)
const tagRaw = 'raw'

export type CodeSegmentInfo = {
/** Code content */
content: string
Expand All @@ -20,7 +23,7 @@ export type CodeSegmentInfo = {
export interface Props {
/** Code */
code: string | CodeSegmentInfo[]
/** Language of given code */
/** Language of given code, language with tag (`gop|raw`) is also supported */
language?: string
/** If code copyable (with a copy button) */
copyable?: boolean
Expand All @@ -32,7 +35,7 @@ export interface Props {

export default function Code({
code,
language = langGop,
language = 'text',
copyable = true,
runnable = true,
editable = true
Expand All @@ -52,8 +55,11 @@ export default function Code({
})
}, [runResult])

runnable = language === langGop && runnable
editable = language === langGop && editable
const [lang, tag] = language.split('|')
const interactive = lang === langGop && tag !== tagRaw

runnable = interactive && runnable
editable = interactive && editable

const runResultView = runnable && runResult != null && (
<pre className={styles.runResult} ref={runResultRef}>
Expand All @@ -76,7 +82,7 @@ export default function Code({
<div className={className}>
<div className={styles.codeSegments}>
{codeSegments.map((seg, i) => (
<CodeSegment key={i} language={language} hasDoc={hasDoc} {...seg} />
<CodeSegment key={i} language={lang} hasDoc={hasDoc} {...seg} />
))}
</div>
{opBtns.length > 0 && (
Expand Down Expand Up @@ -157,7 +163,7 @@ function Tip(props: PropsWithChildren<{}>) {
function Error({ message }: { message: string }) {
return <>
<Tip>Error encountered:</Tip>
{message}
<p className={styles.error}>{message}</p>
</>
}

Expand Down
4 changes: 4 additions & 0 deletions goplus.org/components/Code/style.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,10 @@
margin: 0;
color: #666;
}

.error {
color: #900;
}
}

@include pc {
Expand Down
119 changes: 70 additions & 49 deletions goplus.org/components/Home/Features/content.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ We introduce the rational number as native Go+ types. We use suffix `r` to denot
var a bigint = 1r << 65 // bigint, large than int64
var b bigrat = 4/5r // bigrat
c := b - 1/3r + 3 * 1/2r // bigrat
println(a, b, c)
println a, b, c
var x *big.Int = 1r << 65 // (1r << 65) is untyped bigint, and can be assigned to *big.Int
var y *big.Rat = 4/5r
println(x, y)
println x, y
```

### Map literal
Expand All @@ -34,6 +34,21 @@ c := ["xsw", 3] // []interface{}
empty := [] // []interface{}
```

### Lambda expression

```gop
func plot(fn func(x float64) float64) {
// ...
}
func plot2(fn func(x float64) (float64, float64)) {
// ...
}
plot x => x * x // plot(func(x float64) float64 { return x * x })
plot2 x => (x * x, x + x) // plot2(func(x float64) (float64, float64) { return x * x, x + x })
```

### Deduce struct type

```gop
Expand All @@ -46,10 +61,10 @@ func foo(conf *Config) {
// ...
}
foo({Dir: "/foo/bar", Level: 1})
foo {Dir: "/foo/bar", Level: 1}
```

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.
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.

You also can omit struct types in a return statement. For example:

Expand Down Expand Up @@ -93,8 +108,8 @@ students := [student{"Ken", 90}, student{"Jason", 80}, student{"Lily", 85}]
unknownScore, ok := {x.score for x <- students, x.name == "Unknown"}
jasonScore := {x.score for x <- students, x.name == "Jason"}
println(unknownScore, ok) // output: 0 false
println(jasonScore) // output: 80
println unknownScore, ok // output: 0 false
println jasonScore // output: 80
```

### Check if data exists in a collection
Expand All @@ -121,6 +136,27 @@ for x <- [1, 3, 5, 7, 11, 13, 17], x > 3 {
```


### Range expression (`start:end:step`)

```gop
for i <- :10 {
println i
}
for i := range :10:2 {
println i
}
for i := range 1:10:3 {
println i
}
for range :10 {
println "Range expression"
}
```


### For range of UDT

```gop
Expand All @@ -135,14 +171,14 @@ func (p *Foo) Gop_Enum(proc func(key int, val string)) {
foo := &Foo{}
for k, v := range foo {
println(k, v)
println k, v
}
for k, v <- foo {
println(k, v)
println k, v
}
println({v: k for k, v <- foo})
println {v: k for k, v <- foo}
```

**Note: you can't use break/continue or return statements in for range of udt.Gop_Enum(callback).**
Expand Down Expand Up @@ -170,29 +206,14 @@ func (p *Foo) Gop_Enum() *FooIter {
foo := &Foo{}
for k, v := range foo {
println(k, v)
println k, v
}
for k, v <- foo {
println(k, v)
}
println({v: k for k, v <- foo})
```

### Lambda expression

```gop
func plot(fn func(x float64) float64) {
// ...
}
func plot2(fn func(x float64) (float64, float64)) {
// ...
println k, v
}
plot(x => x * x) // plot(func(x float64) float64 { return x * x })
plot2(x => (x * x, x + x)) // plot2(func(x float64) (float64, float64) { return x * x, x + x })
println {v: k for k, v <- foo}
```

### Overload operators
Expand Down Expand Up @@ -222,16 +243,16 @@ func -(a MyBigInt) MyBigInt { // unary operator
a := Int(1r)
a += Int(2r)
println(a + Int(3r))
println(-a)
println a + Int(3r)
println -a
```


### Error handling

We reinvent the error handling specification in Go+. We call them `ErrWrap expressions`:

```gop
```gop|raw
expr! // panic if err
expr? // return if err
expr?:defval // use defval if err
Expand All @@ -252,23 +273,23 @@ func addSafe(x, y string) int {
return strconv.Atoi(x)?:0 + strconv.Atoi(y)?:0
}
println(`add("100", "23"):`, add("100", "23")!)
println `add("100", "23"):`, add("100", "23")!
sum, err := add("10", "abc")
println(`add("10", "abc"):`, sum, err)
println `add("10", "abc"):`, sum, err
println(`addSafe("10", "abc"):`, addSafe("10", "abc"))
println `addSafe("10", "abc"):`, addSafe("10", "abc")
```

The output of this example is:

```
```gop|raw
add("100", "23"): 123
add("10", "abc"): 0 strconv.Atoi: parsing "abc": invalid syntax
===> errors stack:
main.add("10", "abc")
/Users/xsw/goplus/tutorial/15-ErrWrap/err_wrap.gop:6 strconv.Atoi(y)?
/Users/xsw/tutorial/15-ErrWrap/err_wrap.gop:6 strconv.Atoi(y)?
addSafe("10", "abc"): 10
```
Expand All @@ -285,23 +306,23 @@ How these `ErrWrap expressions` work? See [Error Handling](https://github.com/go
Let's see an example written in Go+:

```gop
import "github.com/goplus/gop/ast/goptest"
import "gop/ast/goptest"
doc := goptest.New(`... Go+ code ...`)!
println(doc.Any().FuncDecl().Name())
println doc.Any().FuncDecl().Name()
```

In many languages, there is a concept named `property` who has `get` and `set` methods.

Suppose we have `get property`, the above example will be:

```gop
import "github.com/goplus/gop/ast/goptest"
import "gop/ast/goptest"
doc := goptest.New(`... Go+ code ...`)!
println(doc.any.funcDecl.name)
println doc.any.funcDecl.name
```

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.
Expand All @@ -314,20 +335,20 @@ You can use Go+ programs as shell scripts now. For example:
```gop
#!/usr/bin/env -S gop run
println("Hello, Go+")
println "Hello, Go+"
println(1r << 129)
println(1/3r + 2/7r*2)
println 1r << 129
println 1/3r + 2/7r*2
arr := [1, 3, 5, 7, 11, 13, 17, 19]
println(arr)
println([x*x for x <- arr, x > 3])
println arr
println [x*x for x <- arr, x > 3]
m := {"Hi": 1, "Go+": 2}
println(m)
println({v: k for k, v <- m})
println([k for k, _ <- m])
println([v for v <- m])
println m
println {v: k for k, v <- m}
println [k for k, _ <- m]
println [v for v <- m]
```

Go [tutorial/20-Unix-Shebang/shebang](https://github.com/goplus/gop/blob/main/tutorial/20-Unix-Shebang/shebang) to get the source code.
Go [20-Unix-Shebang/shebang](https://github.com/goplus/tutorial/blob/main/20-Unix-Shebang/shebang) to get the source code.

0 comments on commit 242bbe2

Please sign in to comment.