суббота, 22 октября 2011 г.

F#

Мне понравился язык F# - потихоньку изучаю его. Кратко поясню: F# - это мультипарадигмальный язык программирования для платформы .Net, поддерживающий функциональное, императивное и объектно-ориентированное программирование. F# статически типизирован, т.е. информация о типах доступна уже на этапе компиляции, что обеспечивает большую надёжность программного кода.

Кроме того, на F# можно писать скрипты! Эти скрипты не интерпретируются, а предварительно компилируются в памяти и уже откомпилированный код запускается на исполнение. За счёт этого скрипты, написанные на F# выполняются гораздо быстрее, чем скрипты, написанные на чистых скриптовых языках.

Сейчас меня интересуют именно скрипты, а не компилируемые приложения, написанные на том же F#. Я решил проверить следующее: поскольку скрипт, написанный на F# предварительно компилируется, то, теоретически, можно сделать так, чтобы скрипт выполнил всё что от него требуется и затем сам себя удалил! Ведь откомпилированный код уже не связан с исходным текстовым fsx-файлом скрипта. Как показала практика - моё предположение оказалось верным. Это приятно радует и будет мною востребовано в механизмах обновления моих программ.

Привожу пример скрипта, написанного мною в качестве теста. Обратите внимание на то, что работа скрипта начинается с того, что он совершенно спокойно сам себя удаляет, и уже затем выполняет всю требующуюся от него работу:

//*********************************************************************************
(*
Скрипт написан на языке F#. Такие скрипты не интерпретируются построчно, а компилируются в момент их запуска, результат компиляции загружается в память и выполняет всю работу.
Поскольку скрипт компилируется - он выполняется гораздо быстрее, чем скрипт, который интерпретируется. Кроме того, поскольку работу выполняет откомпилированный код, находящийся в памяти - связи с исходным текстовым файлом скрипта нет, т.е. можно заставить скрипт выполнить всё что нужно и затем удалить самого себя (т.е. исходный fsx-файл).
*)
open System
open System.IO

//Первым делом удаляем файл текущего скрипта
//Это можно сделать так:
//let file = Path.Combine(__SOURCE_DIRECTORY__, __SOURCE_FILE__)
//File.Delete(file)
//Или так:
let file = __SOURCE_DIRECTORY__ + "\\" + __SOURCE_FILE__
File.Delete(file)

if File.Exists(file) then printfn "Беда: файл не удалён..."
else printfn "Файл успешно удалён!"

//Выводим на консоль информацию о системе
printfn @"Текущий сценарий: ""%s\%s""" __SOURCE_DIRECTORY__ __SOURCE_FILE__
printfn "Текущее время: %A" DateTime.Now
printfn "Имя компьютера (NetBIOS): %s" Environment.MachineName
printfn "Домен: %s" Environment.UserDomainName
printfn "Имя пользователя (логин): %s" Environment.UserName
printfn "Версия операционной системы: %s" Environment.OSVersion.VersionString
printfn "Системный каталог: %s" Environment.SystemDirectory
let xbit condition = if condition then "x64" else "x86"
printfn "Разрядность операционной системы: %s" (xbit Environment.Is64BitOperatingSystem)
printfn "Количество центральных процессоров: %d" Environment.ProcessorCount
printfn "Разрядность текущего процесса: %s" (xbit Environment.Is64BitProcess)
printfn "Объём файла подкачки: %d Мб" Environment.SystemPageSize
printfn "Версия CLR: %A" Environment.Version
0
//*********************************************************************************


Этот код нужно сохранить в текстовый файл с расширением fsx. Запустить его можно либо из Проводника, выбрав из контекстного меню пункт "Run with F# Interactive...", либо из консоли, запустив программу fsi.exe и передав ей в качестве параметра имя нашего fsx-файла. Результат выполнения кода у меня такой:

//*********************************************************************************
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC>fsi "C:\Users\user\documents\visual studio 2010\Projects\FSharpLe
arning\FSharpLearning\Script1.fsx"
Файл успешно удалён!
Текущий сценарий: "C:\Users\user\documents\visual studio 2010\Projects\FSharpLearning\FSharpLearning\Script1.fsx"
Текущее время: 22.10.2011 0:03:32
Имя компьютера (NetBIOS): BUSHCOMP
Домен: BushComp
Имя пользователя (логин): user
Версия операционной системы: Microsoft Windows NT 6.1.7601 Service Pack 1
Системный каталог: C:\Windows\system32
Разрядность операционной системы: x64
Количество центральных процессоров: 8
Разрядность текущего процесса: x86
Объём файла подкачки: 4096 Мб
Версия CLR: 4.0.30319.17020

C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC>
//*********************************************************************************

Как видим, скрипт благополучно удалил сам себя, после чего ещё и выполнил всю требующуюся от него работу. На мой взгляд это очень удобно!

Удалять себя могут и скрипты, написанные на интерпретируемых языках (например на VBScript это можно сделать так: CreateObject("Scripting.FileSystemObject").DeleteFile WScript.ScriptFullName,True ), но поскольку я изучаю F#, то меня приятно радует, что именно в нём такая возможность присутствует.



8 комментариев:

Александр Бауск комментирует...

Интересный синтаксис. А то, что он введён в 2010 версии - следовательно, писать под API, требующие 2008 версии, не получится? Робот 2012, если верить документации, требует VS 2008.

Андрей комментирует...

Возможность писать на F# в MS Visual Studio 2008 имеется. Более подробно на эту тему можно прочитать здесь.

Дима_ комментирует...

Андрей Здравствуй, как я удачно "нагуглил", что я вижу - "Мне понравился язык F#" - честное слово искренне рад. Без обид - с точки зрения функционального подхода - твой пример вобще никакой (это пока классический императивный код) - но я уверен - лиха беда начала - успехов и удачи.

Андрей комментирует...

Написание скриптов - это то, что меня сейчас заинтересовало в первую очередь. Я хочу использовать их для расширения возможностей администрирования AdminCAD. Функциональный стиль программирования в F# я потихоньку (в свободное время) изучаю, но даётся мне это с трудом, ибо непривычно.

Salt комментирует...

Любопытно, есть ли возможность запускать скрипты не в отдельном процессе fsi.exe, а из текущего потока, например, по ходу выполнения команды автокада?

Андрей комментирует...

Чем процесс не устроил? Предполагаю, что появление вопроса обусловлено незнанием о существовании метода System.Diagnostics.Process.WaitForExit...

Salt комментирует...

Процесс не устроил тем, что в нем другое адресное пространство и автокад из него будет доступен только через com interop.

Андрей комментирует...

Понятно. Я пытался разобраться в этом с помощью .Net Reflector (недолго правда...) - безрезультатно.