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