Значение printfn не является функцией и не может быть применено в интерактивном окне F # - PullRequest
2 голосов
/ 11 ноября 2011

Возможно, это что-то простое, но у меня есть файл .fs с простой функцией примера.

let printHello = printfn "%A" "Hello"

Я установил путь поиска для файла .fs, используя

>#I "PathToMyFSFile"

Я загрузил свой файл, используя

>#load "Test.fs"

, который работал нормально.Теперь я хочу вызвать функцию, которая фактически выводит привет на экран, но это оказывается слишком сложным

> Test.printHello;;
val it : unit = ()

Tried Test.printHello () ;;как хорошо, но не работаетКак я могу заставить его печатать «Hello» на экране?

Ответы [ 3 ]

6 голосов
/ 11 ноября 2011

ваш текущий printHello на самом деле не функция. Чтобы сделать это функцией, вам нужно сделать

let printHello() = printfn "%A" "Hello"

Шум (). Тогда все должно работать.

EDIT:

Когда компилятор видит ваше определение

let printHello = printfn "%A" "Hello"

передает его как простой термин данных. Например, рассмотрим эту программу:

let printHello = printfn "%A" "Hello"
printfn "World"
printHello

Будет напечатано "Hello", затем "World". printHello просто имеет тип юнита, поэтому ничего не делает. Сравните это с

let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()

Здесь printHello - это функция. В этом случае функция выполняется только при явном вызове, поэтому выводится "World", а затем "Hello".

5 голосов
/ 11 ноября 2011

Как уже сказал Джон, ваш printHello не является функцией - это значение типа unit.Когда вы предоставляете printfn все необходимые аргументы (как вы это сделали), он выполняет императивную операцию и возвращает unit (это тип с единственным значением, записанным как ()).Вы можете видеть, что написание этой декларации выполняет печать немедленно:

> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()

Когда вы используете printHello позже, оно просто ссылается на это значение unit (которое не несет никакой информации).

Если вы хотите сделать его функцией (типа unit -> unit), которая будет делать что-то при каждом ее выполнении, тогда вы можете использовать пример, который Джон опубликовал.

Функция printfn былане частично применимо , потому что вы задали ему все необходимые параметры (чтобы он мог просто напечатать сразу).Если вы хотите использовать частичное приложение, вы можете использовать что-то вроде:

> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit

Now printHello - это функция, которая ожидает второй параметр и затем запускает:

> printHello "World";;
Hello World
val it : unit = ()

> printHello "F#";;
Hello F#
val it : unit = ()
1 голос
/ 11 ноября 2011

Как уже было сказано в других ответах, "printHello", установленный в (), является единицей, возвращаемое значение printfn - (), консольная печать - побочным эффектом.

используйте Ленивый:

let printHello = Lazy (fun () ->printfn "%A" "Hello")

DEMO

> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once

используйте Seq:

let printHello = seq { printfn "%A" "Hello"; yield ()}

DEMO

> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times
...