ref #16 better processing of the last-block argument
+sample with national-characters vars
This commit is contained in:
parent
194fc8aca6
commit
28b83f9892
37
docs/samples/сумма_ряда.lyng.md
Normal file
37
docs/samples/сумма_ряда.lyng.md
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
# Пример расчета суммы ряда
|
||||||
|
|
||||||
|
Рассмотрим как можно посчитать предел суммы ряда на lyng. Для наивной реализации
|
||||||
|
представим что у нас есть функция рассчитывающая n-й член ряда. Тогда мы можем
|
||||||
|
считать сумму до тех пор, пока отклонение при расчете следующего члена не станет
|
||||||
|
меньше чем заданная погрешность:
|
||||||
|
|
||||||
|
fun сумма_ряда(x, погрешность=0.0001, f) {
|
||||||
|
var сумма = 0
|
||||||
|
for( n in 1..100000) {
|
||||||
|
val следующая_сумма = сумма + f(x, n)
|
||||||
|
if( n > 1 && abs(следующая_сумма - сумма) < погрешность )
|
||||||
|
break следующая_сумма
|
||||||
|
сумма = следующая_сумма
|
||||||
|
}
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
|
||||||
|
Для проверки можно посчитать на хорошо известном ряду Меркатора
|
||||||
|
|
||||||
|
$$ \ln(1+x)=x-{\dfrac {x^{2}}{2}}+{\dfrac {x^{3}}{3}}-\cdots =\sum \limits _{n=0}^{\infty }{\dfrac {(-1)^{n}x^{n+1}}{(n+1)}}=\sum \limits _{n=1}^{\infty }{\dfrac {(-1)^{n-1}x^{n}}{n}}
|
||||||
|
$$
|
||||||
|
|
||||||
|
Который в нашем случае для точки $x = 1$ можно записать так:
|
||||||
|
|
||||||
|
val x = сумма_ряда(1) { x, n ->
|
||||||
|
val sign = if( n % 2 == 1 ) 1 else -1
|
||||||
|
sign * pow(x, n) / n
|
||||||
|
}
|
||||||
|
|
||||||
|
Проверим:
|
||||||
|
|
||||||
|
assert( x - ln(2) < 0.001 )
|
||||||
|
|
||||||
|
Во многих случаях вычисление $n+1$ члена значительно проще cчитается от предыдущего члена, в нашем случае это можно было бы записать через итератор, что мы вскоре добавим.
|
||||||
|
|
||||||
|
(продолжение следует)
|
@ -15,8 +15,7 @@ __Other documents to read__ maybe after this one:
|
|||||||
- [OOP notes](OOP.md)
|
- [OOP notes](OOP.md)
|
||||||
- [math in Lyng](math.md)
|
- [math in Lyng](math.md)
|
||||||
- Some class references: [List], [Real], [Range], [Iterable], [Iterator]
|
- Some class references: [List], [Real], [Range], [Iterable], [Iterator]
|
||||||
- Some samples: [combinatorics](samples/combinatorics.lyng.md)
|
- Some samples: [combinatorics](samples/combinatorics.lyng.md), national vars and loops: [сумма ряда](samples/сумма_ряда.lyng.md). More at [samples folder](samples)
|
||||||
See [samples folder](samples)
|
|
||||||
|
|
||||||
# Expressions
|
# Expressions
|
||||||
|
|
||||||
|
@ -53,7 +53,11 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
|||||||
val value = when {
|
val value = when {
|
||||||
i < callArgs.size -> callArgs[i]
|
i < callArgs.size -> callArgs[i]
|
||||||
a.defaultValue != null -> a.defaultValue.execute(context)
|
a.defaultValue != null -> a.defaultValue.execute(context)
|
||||||
else -> context.raiseArgumentError("too few arguments for the call")
|
else -> {
|
||||||
|
println("callArgs: ${callArgs.joinToString()}")
|
||||||
|
println("tailBlockMode: ${arguments.tailBlockMode}")
|
||||||
|
context.raiseArgumentError("too few arguments for the call")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assign(a, value)
|
assign(a, value)
|
||||||
i++
|
i++
|
||||||
|
@ -140,7 +140,7 @@ class Compiler(
|
|||||||
Token.Type.LPAREN -> {
|
Token.Type.LPAREN -> {
|
||||||
cc.next()
|
cc.next()
|
||||||
// instance method call
|
// instance method call
|
||||||
val args = parseArgs(cc)
|
val args = parseArgs(cc).first
|
||||||
isCall = true
|
isCall = true
|
||||||
operand = Accessor { context ->
|
operand = Accessor { context ->
|
||||||
context.pos = next.pos
|
context.pos = next.pos
|
||||||
@ -552,7 +552,11 @@ class Compiler(
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseArgs(cc: CompilerContext): List<ParsedArgument> {
|
/**
|
||||||
|
* Parse arguments list during the call and detect last block argument
|
||||||
|
* _following the parenthesis_ call: `(1,2) { ... }`
|
||||||
|
*/
|
||||||
|
private fun parseArgs(cc: CompilerContext): Pair<List<ParsedArgument>, Boolean> {
|
||||||
|
|
||||||
val args = mutableListOf<ParsedArgument>()
|
val args = mutableListOf<ParsedArgument>()
|
||||||
do {
|
do {
|
||||||
@ -578,6 +582,7 @@ class Compiler(
|
|||||||
// block after?
|
// block after?
|
||||||
val pos = cc.savePos()
|
val pos = cc.savePos()
|
||||||
val end = cc.next()
|
val end = cc.next()
|
||||||
|
var lastBlockArgument = false
|
||||||
if (end.type == Token.Type.LBRACE) {
|
if (end.type == Token.Type.LBRACE) {
|
||||||
// last argument - callable
|
// last argument - callable
|
||||||
val callableAccessor = parseLambdaExpression(cc)
|
val callableAccessor = parseLambdaExpression(cc)
|
||||||
@ -588,14 +593,16 @@ class Compiler(
|
|||||||
},
|
},
|
||||||
end.pos
|
end.pos
|
||||||
)
|
)
|
||||||
|
lastBlockArgument = true
|
||||||
} else
|
} else
|
||||||
cc.restorePos(pos)
|
cc.restorePos(pos)
|
||||||
return args
|
return args to lastBlockArgument
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun parseFunctionCall(cc: CompilerContext, left: Accessor, blockArgument: Boolean): Accessor {
|
private fun parseFunctionCall(cc: CompilerContext, left: Accessor, blockArgument: Boolean): Accessor {
|
||||||
// insofar, functions always return lvalue
|
// insofar, functions always return lvalue
|
||||||
|
var detectedBlockArgument = blockArgument
|
||||||
val args = if (blockArgument) {
|
val args = if (blockArgument) {
|
||||||
val blockArg = ParsedArgument(
|
val blockArg = ParsedArgument(
|
||||||
parseExpression(cc)
|
parseExpression(cc)
|
||||||
@ -603,7 +610,9 @@ class Compiler(
|
|||||||
)
|
)
|
||||||
listOf(blockArg)
|
listOf(blockArg)
|
||||||
} else {
|
} else {
|
||||||
parseArgs(cc)
|
val r = parseArgs(cc)
|
||||||
|
detectedBlockArgument = r.second
|
||||||
|
r.first
|
||||||
}
|
}
|
||||||
|
|
||||||
return Accessor { context ->
|
return Accessor { context ->
|
||||||
@ -611,7 +620,7 @@ class Compiler(
|
|||||||
v.value.callOn(
|
v.value.callOn(
|
||||||
context.copy(
|
context.copy(
|
||||||
context.pos,
|
context.pos,
|
||||||
args.toArguments(context, blockArgument)
|
args.toArguments(context, detectedBlockArgument)
|
||||||
// Arguments(
|
// Arguments(
|
||||||
// args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
// args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
||||||
// ),
|
// ),
|
||||||
|
@ -1640,4 +1640,49 @@ class ScriptTest {
|
|||||||
""".trimIndent())
|
""".trimIndent())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nationalCharsTest() = runTest {
|
||||||
|
eval("""
|
||||||
|
fun сумма_ряда(x, погрешность=0.0001, f) {
|
||||||
|
var сумма = 0
|
||||||
|
for( n in 1..100000) {
|
||||||
|
val следующая_сумма = сумма + f(x, n)
|
||||||
|
if( n > 1 && abs(следующая_сумма - сумма) < погрешность )
|
||||||
|
break следующая_сумма
|
||||||
|
сумма = следующая_сумма
|
||||||
|
}
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
val x = сумма_ряда(1) { x, n ->
|
||||||
|
val sign = if( n % 2 == 1 ) 1 else -1
|
||||||
|
sign * pow(x, n) / n
|
||||||
|
}
|
||||||
|
assert( x - ln(2) < 0.001 )
|
||||||
|
""".trimIndent())
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// @Test
|
||||||
|
// fun customIteratorTest() = runTest {
|
||||||
|
// eval("""
|
||||||
|
// fun сумма_ряда2(погрешность=0.0001, iterator) {
|
||||||
|
// var сумма = 0
|
||||||
|
// for( n in 1..100000) {
|
||||||
|
// if( !iterator.hasNext() ) break сумма
|
||||||
|
// val следующая_сумма = сумма + iterator.next()
|
||||||
|
// if( n > 1 && abs(следующая_сумма - сумма) < погрешность )
|
||||||
|
// break следующая_сумма
|
||||||
|
// сумма = следующая_сумма
|
||||||
|
// }
|
||||||
|
// else null
|
||||||
|
// }
|
||||||
|
// val
|
||||||
|
// val x = сумма_ряда2(1) { x, n ->
|
||||||
|
// val sign = if( n % 2 == 1 ) 1 else -1
|
||||||
|
// sign * pow(x, n) / n
|
||||||
|
// }
|
||||||
|
// assert( x - ln(2) < 0.001 )
|
||||||
|
// """.trimIndent())
|
||||||
|
// }
|
||||||
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user