Pull to refresh

Emacs таинственный: Путешествие в калькулятор

Reading time11 min
Views9.9K


Ничто так не скрыто от нас, как то, что лежит на поверхности.
Сунь Цзы и Чжугэ Лян (вольный перевод)


Предисловие



Случилось сие в одном из роликов на YouTube. При просмотре программистского урока нужно было срочно перевести 377 в десятичную систему. Мы не стали раскладывать это на тройки бит, представлять степени восьмёрки или просто не обращать на это внимание и пропустить этот неважный момент. Мы запустили калькулятор в операционной системе, пододвинули его окно к центру экрана и там всё выяснили. Да, это оно — число 255.

Конечно, не нужно рассказывать, что бывает в более сложных случаях. Порой дело доходит до листика в тетради, лежащей рядом с компьютером как раз для таких случаев. У каждого найдётся парабола или что-то около того, пересекающее что-то около того.

Первый контакт



Как и следовало ожидать, при использовании Emacs на протяжении месяцев или просто многих лет наступает Emacs головного мозга. Поэтому такие случаи не проходят даром и среди ночи в голове возникает вопрос: «Как же всё-таки в Emacs'е перевести 377? Он хотя бы это умеет? Ну, хотя бы 8 возведёт в степень?».

Наутро, зарядившись энергией в виде чая с горстью шоколадных конфет, мы открываем Emacs и начинаем его исследование.



Начинаем с операций



Понятно, что введя Alt + x и calc , мы первым делом видим обычный стековый калькулятор, которых писали, наверное, штук сто вот этими вот руками. И как бы не хотелось повторять этот путь в сто первый раз, обнаружив, что он не умеет ничего.

Методом тыка сначала делаем + — * /

5 <RET> 7 <RET> +

5 <RET> 7 <RET> -

5 <RET> 7 <RET> *

5 <RET> 7 <RET> /


Потом

8 <RET> 8 <RET> *


О! А вот и квадрат восьмёрки! А где квадрат, там и куб!

Открываем хелп



Конечно, все знают, что русский человек (сссрский, имперский и др.) не будет начинать с инструкции, а сначала попробует всё сломать, потом починить, а потом уже инструкцию читать в поисках пропущенных секретов.

Не скажу, что в этот раз с инструкции всё началось, так как в отличие от многих я не отключаю меню Emacs'а, а пользуюсь им для вспоминания сочетаний клавиш во всяких редких режимах.

Вот и в этот раз я начал обзор с меню калькулятора



Для того, чтобы открыть хелп, нужно ввести Ctrl + x + * + i . А чтобы открыть туториал, нужно ввести Ctrl + x + * + t .

Их по-разному можно открыть, но, как показала практика, сочетание Ctrl + x + * + <клавиша> используется очень часто и сделано специально для удобного управления калькулятором в процессе другой работы.

Поэтому открыть калькулятор можно через Ctrl + x + * + c , а запустить калькулятор в текущем буфере можно через Ctrl + x + * + e .

Описание клавиш
calc-dispatch-help is an interactive compiled Lisp function.

(calc-dispatch-help ARG)

C-x* is a prefix key sequence; follow it with one of these letters:

For turning Calc on and off:
C calc. Start the Calculator in a window at the bottom of the screen.
O calc-other-window. Start the Calculator but don't select its window.
B calc-big-or-small. Control whether to use the full Emacs screen for Calc.
Q quick-calc. Use the Calculator in the minibuffer.
K calc-keypad. Start the Calculator in keypad mode (X window system only).
E calc-embedded. Use the Calculator on a formula in this editing buffer.
J calc-embedded-select. Like E, but select appropriate half of => or :=.
W calc-embedded-word. Like E, but activate a single word, i.e., a number.
Z calc-user-invocation. Invoke Calc in the way you defined with `Z I' cmd.
X calc-quit. Turn Calc off.

For moving data into and out of Calc:
G calc-grab-region. Grab the region defined by mark and point into Calc.
R calc-grab-rectangle. Grab the rectangle defined by mark, point into Calc.
: calc-grab-sum-down. Grab a rectangle and sum the columns.
_ calc-grab-sum-across. Grab a rectangle and sum the rows.
Y calc-copy-to-buffer. Copy a value from the stack into the editing buffer.

For use with Embedded mode:
A calc-embedded-activate. Find and activate all :='s and =>'s in buffer.
D calc-embedded-duplicate. Make a copy of this formula and select it.
F calc-embedded-new-formula. Insert a new formula at current point.
N calc-embedded-next. Advance cursor to next known formula in buffer.
P calc-embedded-previous. Advance cursor to previous known formula.
U calc-embedded-update-formula. Re-evaluate formula at point.
` calc-embedded-edit. Use calc-edit to edit formula at point.

Documentation:
I calc-info. Read the Calculator manual in the Emacs Info system.
T calc-tutorial. Run the Calculator Tutorial using the Emacs Info system.
S calc-summary. Read the Summary from the Calculator manual in Info.

Miscellaneous:
L calc-load-everything. Load all parts of the Calculator into memory.
M read-kbd-macro. Read a region of keystroke names as a keyboard macro.
0 (zero) calc-reset. Reset Calc stack and modes to default state.

Press `*' twice (`C-x * *') to turn Calc on or off using the same
Calc user interface as before (either C-x * C or C-x * K; initially C-x * C).



Поднимаем планку



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

Наибольший общий делитель (НОД) теперь можно не писать, здесь он просто есть. Надо ввести два числа и нажать k g, где k означает комбинаторику, а g — gcd (Greatest Common Divisor).

Факториал 3000 (своеобразная проверка на скорость) вычисляется не без труда, но всё же вычисляется секунд за пятнадцать.

Транспонирование матрицы, нахождение её определителя или скалярное умножение векторов выполняется легко и со свистом.

На минуту я забыл, за чем пришёл, выполняя операции одну за другой, не веря собственным глазам. А за чем же я пришёл?

Продолжаем



На второй день стало интересно, вычислит ли он систему уравнений методом Крамера. Раз определители есть, то и решение методом Крамера можно найти. Раньше-то я в редакторе это писал много раз, даже навыки уже сложились по вычислению определителей в редакторе.

Но это не потребовалось. Оказалось, что достаточно просто ввести три уравнения, а потом запросить их решение. Да, прямо как в Вольфраме.

Найдём первую попавшуюся систему

 2y +  x +  z = -1
 -z -  y + 3x = -1
-2x + 3z + 2y =  5


Надо просто её выделить Ctrl + x + h , скопировать Alt + w , перейти в калькулятор Ctrl + x + * + * , вставить её Ctrl + y , упаковать уравнения в вектор 3 v p , нажать a P и в ответ на вопрос «По каким переменным искать корни?» ввести x y z .

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

[[ 0., -2., 3. ]] 2y +  x +  z = -1
 -z -  y + 3x = -1
-2x + 3z + 2y =  5


Если бы мы курсор оставили в конце системы уравнений, то ответ вставился бы туда.

Пришло время развернуться



Сила стека



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

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

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

К примеру, есть у нас число пять в стеке

1: 5


Если мы нажмём <RET> (Enter), то оно скопируется и у нас будет

2: 5
1: 5


Вот эта двойка равна количеству элементов в стеке, она же является адресом первого числа пять, а число 1 является адресом второго числа пять.

У команды <RET> есть аргумент, который по умолчанию равен 1. Когда мы нажимаем <RET> , он копирует столько элементов от вершины стека (вершина — в самом низу). Поэтому, если мы введём Alt + 2 + <RET> , он возьмёт два элемента и скопирует их

4: 5
3: 5
2: 5
1: 5


Если же аргумент отрицательный, то он берёт элемент с таким адресом (если минус убрать). Поэтому, если мы введём теперь Alt + — + 4 + <RET> , он скопирует элемент по адресу 4

5: 5
4: 5
3: 5
2: 5
1: 5


Большинство основных операций работают по той же схеме. Если нужно удалить три элемента, то пишем Alt + 3 + <DEL> , где <DEL> — это backspace. Если же нужно удалить элемент с адресом 3, то пишем Alt + — + 3 + <DEL> .

Если почитать хелп ещё более подробно, то к этим операциям можно найти такие своеобразные операции из антимира, состоящие из чёрной материи. Например, для <RET> существует операция Ctrl + j , для <DEL> существует Alt + <DEL> , а для <TAB> существует Alt + <TAB> .

Смысл этих операций точно такой же, только аргумент меняется по знаку. Поэтому, если ввести Alt + 3 + Ctrl + j , то он не три элемента скопирует, а элемент с адресом 3, а если ввести отрицательный аргумент, то он скопирует не элемент с адресом 3, а три элемента.

Если нужно очистить весь стек, то нужно нажать Alt + 0 + <DEL> .

Есть множество путей



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

Например, как можно ввести матрицу?

Самое первое, что приходит на ум, — это написать её в буфере и потом просто скопировать.

Вот это

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]


Превращается вот в это

1: [ [ 1, 2, 3 ]
  &nbsp  [ 4, 5, 6 ]
  &nbsp  [ 7, 8, 9 ] ]


Второе, что приходит на ум, — это использование внутреннего средства.

Матрица — это три вектора

1 <RET> 2 <RET> 3 <RET> 3 v p
4 <RET> 5 <RET> 6 <RET> 3 v p
7 <RET> 8 <RET> 9 <RET> 3 v p
3 v p


Третье, что приходит на ум, — это использование внутреннего и удобного средства.

1 <RET> 2 <RET> 3 <RET> 4 <RET> 5 <RET> 6 <RET> 7 <RET> 8 <RET> 9 <RET>
[3, 3]
v p


И четвертое, что приходит на ум, — «А её нельзя просто ввести?»

[ 1 <SPC> 2 <SPC> 3 ; 4 <SPC> 5 <SPC> 6 ; 7 <SPC> 8 <SPC> 9 ] ]


У команды pack есть симметричная — unpack, поэтому, если нужно разложить матрицу на векторы или вектор разложить на числа, то мы просто нажимаем v u .

Привлекаем внешние средства



По мере ковыряния в калькуляторе вдруг начинаешь обращать внимание на окружающие буферы и постепенно возникает вопрос: «А какие средства обычного Emacs'а можно привлечь при работе в калькуляторе?»

Поначалу мы просто находим n-ую производную многочлена путём записи макроса и повторения его n раз через аргумент макроса.

Например, вводим выражение

' x^5 + 4 x^3 + 2 x + 1 <RET>


Затем нажимаем F3, чтобы начать запись макроса. Потом нажимаем a d, чтобы вычислить производную. Затем на вопрос «По какой переменной?» вводим x . Потом нажимаем F4, чтобы закончить запись макроса.

Делаем отмену вычисления, нажав Ctrl + / или применяя внутреннюю отмену калькулятора — букву U.

Имея первоначальное выражение

1: x^5 + 4 x^3 + 2 x + 1


Нажимаем Alt + 3 + F4 и в результате имеем третью производную

1: 60 x^2 + 24


Если же мы нажмём Ctrl + x + z , а потом z z , то мы постепенно получим ноль.

Уходим во внешний мир



Через какое-то время калькулятор закрывается и мы возвращаемся к нашей обычной работе, к нашим обычным развлечениям.

И вот в один прекрасный момент мы читаем, в Emacs'е естественно, историю про лису, которая прыгала-прыгала через ленивую собаку и прыгнула 1024 раза. Постойте, скажете вы, разве лиса может прыгнуть столько раз прямо точь в точь, если она не компьютерная? Надо это дело исправить.

У нас имеется следующий текст

The quick brown fox has jumped over the lazy dog 1024 times.


Наводим курсор на 1024 и осторожно нажимаем Ctrl + x + * + w . Дальше нажимаем Q, а потом так же осторожно нажимаем Ctrl + x + * + w .

И у нас получается

The quick brown fox has jumped over the lazy dog 32 times.


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

А вот то самое



Вспомнил, за чем я заходил

Ctrl + x + * + *
8#377 <RET>
d 2
d 8
d 6
d 0
Ctrl + x + * + *


И напоследок



Было время, когда я писал функцию на питоне

2016
1
1
Alt + - + 14 v p
255
+


Прилагаю тут список единиц, которые он может конвертировать, в калькуляторе они находятся по u v .

Список единиц
Calculator Units Table:

(All definitions are exact unless marked with an asterisk (*).)

Unit Type Definition Description

m m Meter (base unit)
in 2.54 cm Inch
ft 12 in Foot
yd 3 ft Yard
mi 5280 ft Mile
au 149597870691 m (*) Astronomical Unit
lyr c yr Light Year
pc 3.0856775854 10^16 m (*) Parsec (**)
nmi 1852 m Nautical Mile
fath 6 ft Fathom
fur 660 ft Furlong
mu 1 um Micron
mil (1/1000) in Mil
point (1/72) in Point (PostScript convention)
Ang 10^-10 m Angstrom
mfi mi + ft + in Miles + feet + inches
texpt (100/7227) in Point (TeX convention) (**)
texpc 12 texpt Pica (TeX convention) (**)
texbp point Big point (TeX convention) (**)
texdd (1238/1157) texpt Didot point (TeX convention) (**)
texcc 12 texdd Cicero (TeX convention) (**)
texsp (1/65536) texpt Scaled TeX point (TeX convention) (**)

hect 10000 m^2 Hectare
a 100 m^2 Are
acre (1/640) mi^2 Acre
b 10^-28 m^2 Barn

L 10^-3 m^3 Liter
l L Liter
gal 4 qt US Gallon
qt 2 pt Quart
pt 2 cup Pint (**)
cup 8 ozfl Cup
ozfl 2 tbsp Fluid Ounce
floz 2 tbsp Fluid Ounce
tbsp 3 tsp Tablespoon
tsp 4.92892159375 ml Teaspoon
vol tsp+tbsp+ozfl+cup+pt+qt+gal Gallons + ... + teaspoons
galC galUK Canadian Gallon
galUK 4.54609 L UK Gallon

s s Second (base unit)
sec s Second
min 60 s Minute
hr 60 min Hour
day 24 hr Day
wk 7 day Week
hms wk + day + hr + min + s Hours, minutes, seconds
yr 365.25 day Year (Julian)
Hz 1 / s Hertz

mph mi / hr Miles per hour
kph km / hr Kilometers per hour
knot nmi / hr Knot
c 299792458 m / s Speed of light

ga 9.80665 m / s^2 "g" acceleration

g g Gram (base unit)
lb 16 oz Pound (mass)
oz 28.349523125 g Ounce (mass)
ton 2000 lb Ton
tpo ton + lb + oz Tons + pounds + ounces (mass)
t 1000 kg Metric ton
tonUK 1016.0469088 kg UK ton
lbt 12 ozt Troy pound
ozt 31.10347680 g Troy ounce
ct 0.2 g Carat
u 1.660538782 10^-27 kg (*) Unified atomic mass

N m kg / s^2 Newton
dyn 10^-5 N Dyne
gf ga g Gram (force)
lbf ga lb Pound (force)
kip 1000 lbf Kilopound (force)
pdl 0.138254954376 N Poundal

J N m Joule
erg 10^-7 J Erg
cal 4.1868 J International Table Calorie
calth 4.184 J Thermochemical Calorie
Cal 1000 cal Large Calorie
Btu 1055.05585262 J International Table Btu
eV ech V Electron volt
ev eV Electron volt
therm 105506000 J EEC therm
invcm h c / cm Energy in inverse centimeters
Kayser invcm Kayser (inverse centimeter energy)
men 100 / invcm Inverse energy in meters
Hzen h Hz Energy in Hertz
Ken k K Energy in Kelvins
Wh W hr Watt hour
Ws W s Watt second

W J / s Watt
hp 550 ft lbf / s Horsepower
hpm 75 m kgf / s Metric Horsepower

K K K Degree Kelvin (base unit)
dK K K Degree Kelvin
degK K K Degree Kelvin
dC C K Degree Celsius
degC C K Degree Celsius
dF F (5/9) K Degree Fahrenheit
degF F (5/9) K Degree Fahrenheit

Pa N / m^2 Pascal
bar 10^5 Pa Bar
atm 101325 Pa Standard atmosphere
Torr (1/760) atm Torr
mHg 1000 Torr Meter of mercury
inHg 25.4 mmHg Inch of mercury
inH2O 2.490889 10^2 Pa (*) Inch of water
psi lbf / in^2 Pounds per square inch

P (1/10) Pa s Poise
St 10^-4 m^2 / s Stokes

A A Ampere (base unit)
C A s Coulomb
Fdy ech Nav Faraday
e ech Elementary charge
ech 1.602176487 10^-19 C (*) Elementary charge
V W / A Volt
ohm V / A Ohm
Ω ohm Ohm
mho A / V Mho
S A / V Siemens
F C / V Farad
H Wb / A Henry
T Wb / m^2 Tesla
Gs 10^-4 T Gauss
Wb V s Weber

cd cd Candela (base unit)
sb 10000 cd / m^2 Stilb
lm cd sr Lumen
lx lm / m^2 Lux
ph 10000 lx Phot
fc lm / ft^2 Footcandle
lam 10000 lm / m^2 Lambert
flam (1 / pi) cd / ft^2 Footlambert

Bq 1 / s Becquerel
Ci 37 10^9 Bq Curie
Gy J / kg Gray
Sv Gy Sievert
R 258 10^-6 C / kg Roentgen
rd (1/100) Gy Rad
rem rd Rem

mol mol Mole (base unit)

rad rad Radian (base unit)
circ 2 pi rad Full circle
rev circ Full revolution
deg circ / 360 Degree
arcmin deg / 60 Arc minute
arcsec arcmin / 60 Arc second
grad circ / 400 Grade
rpm rev / min Revolutions per minute

sr sr Steradian (base unit)

h 6.62606896 10^-34 J s (*) Planck's constant
hbar h / (2 pi) Planck's constant
mu0 4 pi 10^-7 H / m Permeability of vacuum
μ0 mu0 Permeability of vacuum
eps0 1 / (mu0 c^2) Permittivity of vacuum
ε0 eps0 Permittivity of vacuum
G 6.67428 10^-11 m^3/(kg s^2) (*) Gravitational constant
Nav 6.02214179 10^23 / mol (*) Avogadro's constant
me 9.10938215 10^-31 kg (*) Electron rest mass
mp 1.672621637 10^-27 kg (*) Proton rest mass
mn 1.674927211 10^-27 kg (*) Neutron rest mass
mmu 1.88353130 10^-28 kg (*) Muon rest mass
mμ 1.88353130 10^-28 kg (*) Muon rest mass
Ryd 10973731.568527 /m (*) Rydberg's constant
k 1.3806504 10^-23 J/K (*) Boltzmann's constant
alpha 7.2973525376 10^-3 (*) Fine structure constant
α 7.2973525376 10^-3 (*) Fine structure constant
muB 927.400915 10^-26 J/T (*) Bohr magneton
muN 5.05078324 10^-27 J/T (*) Nuclear magneton
mue -928.476377 10^-26 J/T (*) Electron magnetic moment
mup 1.410606662 10^-26 J/T (*) Proton magnetic moment
R0 8.314472 J/(mol K) (*) Molar gas constant
V0 22.710981 10^-3 m^3/mol (*) Standard volume of ideal gas

Np Np Neper (base unit)
dB (ln(10) / 20) Np decibel

Unit Prefix Table:

Y 10^24 Yotta
Z 10^21 Zetta
E 10^18 Exa
P 10^15 Peta
T 10^12 Tera
G 10^9 Giga
M 10^6 Mega
k K 10^3 Kilo
h H 10^2 Hecto
D 10^1 Deka
d 10^-1 Deci
c 10^-2 Centi
m 10^-3 Milli
u μ 10^-6 Micro
n 10^-9 Nano
p 10^-12 Pico
f 10^-15 Femto
a 10^-18 Atto
z 10^-21 zepto
y 10^-24 yocto

(**) When in TeX or LaTeX display mode, the TeX specific unit
names will not use the `tex' prefix; the unit name for a
TeX point will be `pt' instead of `texpt', for example.
To avoid conflicts, the unit names for pint and parsec will
be `pint' and `parsec' instead of `pt' and `pc'.

Tags:
Hubs:
+13
Comments21

Articles

Change theme settings