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)
|
||||
- [math in Lyng](math.md)
|
||||
- Some class references: [List], [Real], [Range], [Iterable], [Iterator]
|
||||
- Some samples: [combinatorics](samples/combinatorics.lyng.md)
|
||||
See [samples folder](samples)
|
||||
- Some samples: [combinatorics](samples/combinatorics.lyng.md), national vars and loops: [сумма ряда](samples/сумма_ряда.lyng.md). More at [samples folder](samples)
|
||||
|
||||
# Expressions
|
||||
|
||||
|
@ -53,7 +53,11 @@ data class ArgsDeclaration(val params: List<Item>, val endTokenType: Token.Type)
|
||||
val value = when {
|
||||
i < callArgs.size -> callArgs[i]
|
||||
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)
|
||||
i++
|
||||
|
@ -140,7 +140,7 @@ class Compiler(
|
||||
Token.Type.LPAREN -> {
|
||||
cc.next()
|
||||
// instance method call
|
||||
val args = parseArgs(cc)
|
||||
val args = parseArgs(cc).first
|
||||
isCall = true
|
||||
operand = Accessor { context ->
|
||||
context.pos = next.pos
|
||||
@ -552,7 +552,11 @@ class Compiler(
|
||||
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>()
|
||||
do {
|
||||
@ -578,6 +582,7 @@ class Compiler(
|
||||
// block after?
|
||||
val pos = cc.savePos()
|
||||
val end = cc.next()
|
||||
var lastBlockArgument = false
|
||||
if (end.type == Token.Type.LBRACE) {
|
||||
// last argument - callable
|
||||
val callableAccessor = parseLambdaExpression(cc)
|
||||
@ -588,14 +593,16 @@ class Compiler(
|
||||
},
|
||||
end.pos
|
||||
)
|
||||
lastBlockArgument = true
|
||||
} else
|
||||
cc.restorePos(pos)
|
||||
return args
|
||||
return args to lastBlockArgument
|
||||
}
|
||||
|
||||
|
||||
private fun parseFunctionCall(cc: CompilerContext, left: Accessor, blockArgument: Boolean): Accessor {
|
||||
// insofar, functions always return lvalue
|
||||
var detectedBlockArgument = blockArgument
|
||||
val args = if (blockArgument) {
|
||||
val blockArg = ParsedArgument(
|
||||
parseExpression(cc)
|
||||
@ -603,7 +610,9 @@ class Compiler(
|
||||
)
|
||||
listOf(blockArg)
|
||||
} else {
|
||||
parseArgs(cc)
|
||||
val r = parseArgs(cc)
|
||||
detectedBlockArgument = r.second
|
||||
r.first
|
||||
}
|
||||
|
||||
return Accessor { context ->
|
||||
@ -611,7 +620,7 @@ class Compiler(
|
||||
v.value.callOn(
|
||||
context.copy(
|
||||
context.pos,
|
||||
args.toArguments(context, blockArgument)
|
||||
args.toArguments(context, detectedBlockArgument)
|
||||
// Arguments(
|
||||
// args.map { Arguments.Info((it.value as Statement).execute(context), it.pos) }
|
||||
// ),
|
||||
|
@ -1640,4 +1640,49 @@ class ScriptTest {
|
||||
""".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