Итак, я работаю над небольшим проектом, как вы можете сказать в заголовке, я делаю интерпретатор BrainFuck в f#, и я новичок в этом языке, но это весело, за исключением того, что вы боретесь с большим количеством компилятора, но я привык к этому, потому что Раньше я использовал ржавчину, но, кроме того, мне кажется, что символы выполняются только один раз. Я знаю, что это неэффективно и не полностью функционально, но сейчас я просто работаю. Вот мой код
main.fs
open System
open System.IO
let mutable reg : int array = Array.zeroCreate 50
let mutable ptr = 0
let mutable larr : int array = Array.zeroCreate 50
let mutable lptr = 0
let mutable pc = 0
let result = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
let prog = result.ToCharArray()
let startLoop =
larr.[lptr] <- pc
printfn "STARTING LOOP AT %d" larr.[lptr]
lptr <- lptr + 1
let doEnd =
pc <- larr.[lptr]
while larr.[lptr - 1] > 0 do
ptr <- larr.[lptr - 1]
larr.[lptr - 1] <- larr.[lptr - 1] - 1
let endLoop =
lptr <- lptr - 1
if reg.[ptr] = 0 then pc <- pc
else doEnd
let doPlus =
reg.[ptr] <- (reg.[ptr] + 1) % 265
printfn "ADDING"
let doMinus =
reg.[ptr] <- (reg.[ptr] - 1) % 265
printfn "SUB"
let doInc =
ptr <- (ptr + 1) % 265
printfn "INC"
let doDec =
ptr <- (ptr - 1) % 265
printfn "MINUS"
let doPrt =
printfn "%c" (reg.[ptr] |> char)
let doSloop =
startLoop
printfn "START LOOP"
let doEloop =
endLoop
printfn "END LOOP"
let exec =
while pc < prog.Length do
let i = prog.[pc]
if i = '+' then doPlus
elif i = '-' then doMinus
elif i = '>' then doInc
elif i = '<' then doDec
elif i = '.' then doPrt
elif i = '[' then doSloop
elif i = ']' then doEloop
else 1 |> ignore
pc <- pc + 1
exec
Я думаю, что @ s952163 правильный. Но технически не void
, а unit
. См. learn.microsoft.com/en-us/dotnet/fsharp/language-reference/…
Добро пожаловать в сообщество F#.
Вот более функциональный стиль написания вашей программы. Это только начало, но я надеюсь, что оно даст вам некоторые идеи о том, как действовать дальше. В конечном счете, вы захотите по возможности избегать изменяемых значений, и, вероятно, первым шагом к этому будет написание функций с параметрами, отличными от unit.
let result = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."
let doPlus () =
// reg.[ptr] <- (reg.[ptr] + 1) % 265
printfn "ADDING"
let doMinus () =
// reg.[ptr] <- (reg.[ptr] - 1) % 265
printfn "SUB"
let doDefault () = printfn ""
let funcs =
[|
'+', doPlus
'-', doMinus
|] |> Map.ofArray
let exec () =
result
|> Seq.iteri (fun i c ->
printf "%03d: " i
match funcs.TryFind(c) with
| Some func -> func ()
| None -> doDefault ()
)
exec ()
В чем именно заключается ваш вопрос? Вы имеете в виду, что вы просто определяете значения вместо функций? Функциям нужны входные данные, и они могут принимать
void
, если это необходимо. Определите это такlet exec() =
и вызовите его с помощьюexec()
, и это относится ко всему остальному, что является функцией в вашем коде.